C: sizeof (zeigerinhalt)

Gast #1784319
Lesenswert?

Hallo,
habe eine Frage zu C.

Ich initialisiere ein int array[3] und verwende darauf sizeof(array).
Dabei erhalte ich 12 (= 3*4bit) was Sinn macht.

Nun übergebe ich den Pointer data an eine Funktion und will
intern wieder diese 12 bestimmen.(zur Fehlerkontrolle)
allerdings erhalte ich sowohl bei sizeof(data) oder sizeof(*data) = 4.

Wie komm ich an die 12 ran?

Gruß
Jan
Gast #1784327
Lesenswert?

Gar nicht. Bei der Übergabe an die Funktion geht die Information über 
die Arraygröße verloren. Es geht nur über einen zusätzlichen formalen 
Parameter:
1
void function (
2
    int * data    // Datenfeld
3
    , int length  // Anzahl Elemente im Datenfeld
4
    )
5
{
6
    int i;
7
    for (i = 0; i < length; i++)
8
    {
9
        // do something with data[i]
10
    }
11
}
12

13
int somedata[3];
14

15
int main (void)
16
{
17
    function (
18
        somedata
19
        , sizeof (somedata) / sizeof (*somedata)  // das hier liefert 3
20
    );
21
}
Gast #1784358
Lesenswert?

> Ich initialisiere ein int array[3]...
> Dabei erhalte ich 12 (= 3*4bit) was Sinn macht.
Macht keinen Sinn. Ein int ist in .NET 32-Bit, und auf nem "normalen" 
System 16-Bit. Daher vermute ich, dass du .NET programmierst, was dann 
korrekt ist:
3x 32-Bit = 3x 4 Byte = 12

> Nun übergebe ich den Pointer data an eine Funktion und will
> intern wieder diese 12 bestimmen.(zur Fehlerkontrolle)
> allerdings erhalte ich sowohl bei sizeof(data) oder sizeof(*data) = 4.
Zeig doch mal, WIE du übergibst.

Ralf
Gast #1784370
Lesenswert?

Oh ja,
du hast recht es sind 3*4 Byte.

übergeben tue ich so: (also die Funktionsdefinition)
function(WORD *data)

prinzipiell will ich genau das tun, was tuppes implementiert hat.
Folglich scheint das nich zugehen ohne, dass ich die Länge übergebe.
#1784401
Lesenswert?

Noch ein genereller Hinweis zu sizeof(): Dieser Operator wird bereits 
zum Kompilierzeitpunkt ausgewertet. Daher wirst du den niemals zur 
Fehlerkontrolle einsetzen können. Arrays musst du in C fast immer mit 
einer Längenangabe ausstatten, sonst ist diese Information verloren. Die 
Ausnahme sind Strings (char[]), die definitionsgemäss per Nullbyte 
abgeschlossen werden. Das lässt sich natürlich auch für andere Arrays 
anwenden, ist aber eher unüblich.

Gruss,
Philipp
Gast #1785902
Lesenswert?

>> Macht keinen Sinn. Ein int ist in .NET 32-Bit, und auf nem "normalen"
>> System 16-Bit.
> also bei mir ist ein int auch 32bit unter c,c++.
Ähm... Okay, sorry, wieder was gelernt. Kann sein, dass ich bei der 
Antwort entweder noch in Uralt-16Bit-PC-Zeiten war, oder 
(wahrscheinlicher) bei meinem C-Compiler für Microcontroller :)

Ralf
Gast #1786061
Lesenswert?

Sven P. schrieb:
> Gibt mehrere Möglichkeiten.
>
> Wenn der Vektor immer gleichlang ist:
1
void funktion(int vektor[10]);

Das bringt gar nichts. Die 10 wird ignoriert, also ist das das gleiche 
wie
1
void funktion(int vektor[]);
was wiederum das gleiche ist wie:
1
void funktion(int* vektor);

Die einzige Möglichkeit wäre, einen Zeiger auf das Array zu übergeben:
1
void funktion(int (*vektor)[10]);

Dann bekommt man innerhalb der Funktion mit:
1
groesse = sizeof *vektor;
die Größe zurück.
Gast #1786077
Lesenswert?

Rolf Magnus schrieb:
> Sven P. schrieb:
>> Gibt mehrere Möglichkeiten.
>>
>> Wenn der Vektor immer gleichlang ist:
>
1
> void funktion(int vektor[10]);
2
>
>
> Das bringt gar nichts. Die 10 wird ignoriert, also ist das das gleiche
> wie [...]

War so auch nicht gemeint. War eher so gemeint, dass man Länge 10 
annimmt und der Compiler im Zweifelsfall meckert. Verlangt natürlich 
nach etwas Disziplin.
Gast #1786857
Lesenswert?

Rolf Magnus schrieb:
> Sven P. schrieb:
>> War so auch nicht gemeint. War eher so gemeint, dass man Länge 10
>> annimmt und der Compiler im Zweifelsfall meckert. Verlangt natürlich
>> nach etwas Disziplin.
>
> Gibt es Compiler, die da meckern?

Mir ist keiner bekannt, deshalb ja die Disziplin :-)
Ne, sollte man vermutlich eher als Konvention verstehen, die Sache 
lesbar zu machen. Natürlich ginge auch ein einfacher Zeiger (int *), 
aber dann sieht man nicht mehr auf den ersten Blick die geforderte 
(Mindest-)Länge.
#1787013
Lesenswert?

in C++ könnte man die Array-Länge als Template-Parameter vom Compiler 
automatisch einfüllen lassen, mit Konstrukten wie:
1
  namespace {
2
    template<typename text>
3
    class something_i {};
4

5
    template<int len>
6
    class something_i<char[len]> {
7
    public:
8
      static void do_something(const char op[len]) {
9
         for(int i=0; i<len; ++i) {...}
10
      }
11
    };
12
  }
13
  template<typename text>
14
  void do_something(const text & op) {
15
    something_i<text>::do_something(op);
16
  }
17

18
  ....
19

20
  do_something("Hallo Welt");
Würde in den Beispiel ein strlen einsparen, und trotzdem mit "\000" 
innerhalb der String-Konstante funktionieren.

Aber wenn man eh C++ nimmt, geht das alles sowieso viel besser mit 
std::vector, std::string &co.
#1787014
Lesenswert?

Sven P. schrieb:
> Rolf Magnus schrieb:
>> Sven P. schrieb:
>>> War so auch nicht gemeint. War eher so gemeint, dass man Länge 10
>>> annimmt und der Compiler im Zweifelsfall meckert. Verlangt natürlich
>>> nach etwas Disziplin.
>>
>> Gibt es Compiler, die da meckern?
>
> Mir ist keiner bekannt, deshalb ja die Disziplin :-)

Und genau aus dem Grund halt ich diese [] Schreibweise in Argumentlisten 
für problematisch: Sie suggeriert etwas, was einfach nicht stimmt.
Gast #1787785
Lesenswert?

So kann man das auch sehen. Aber Makros suggerieren auch etwas, das 
nicht ist.

Katze -> Schwanz :-}

Die Schreibweise mit [] im Prototyp hat hingegen doch einen Sinn. Dann 
nämlich, wenn die Vektorlängen eine Rolle spielen, etwa bei 
mehrdimensionalen Vektoren. Dann erspart man sich Zeigerrechnung.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren