Forum: Compiler & IDEs Funktionsaufruf mit Zeiger


von Markus Reichert (Gast)


Lesenswert?

Hallo zusammen,

ich arbeite mich gerade für meine Diplomarbeit in C ein, habe noch keine 
große Erfahrung mit der Sprache und muss u.a. vorhandene Module 
verwenden.

Jetzt wird in einer früheren Arbeit eine Funktion so deklariert:

void aes(char *eingabepuffer)
{
}

Der Aufruf wird folgendermaßen angegeben:

char array[100];
aes(array);

Meiner Meinung nach funktioniert das nicht und müsste doch so aussehen:

aes(&array);

Oder liege ich falsch?

Gehen beide Varianten? Wenn ja, was ist der Unterschied?

Wäre super, wenn mir jemand kurz helfen könnte.

Danke und Gruß
Markus

von arsh0r (Gast)


Lesenswert?

array liefert eine zeiger auf das erste element zurück. &array liefert 
die adresse des zeigers auf das erste element zurück, würde also in dem 
fall zu einem fehler führen...

von Peter D. (peda)


Lesenswert?

Für den Compiler sind Felder und Pointer das gleiche.

Der Unterschied besteht nur in der SRAM-Belegung.

Ein Pointer belegt 2 Byte, worin die Adresse gespeichert wird, auf die 
er mal zeigen soll.

Ein Feld belegt genau den Speicher für den Inhalt. Da die Adresse vom 
Linker aufgelöst wird, braucht ein Feld keinen extra Speicher für die 
Adresse.

Der Zugriff erfolgt auf beides über die Adresse.

(p+5) ist identisch mit &p[5]


Peter

von Robert (Gast)


Lesenswert?

array zeigt auf das Element 0 des Feldes.
Alternativ kann man noch schreiben &array[0].

von Rolf Magnus (Gast)


Lesenswert?

> array liefert eine zeiger auf das erste element zurück.

Genauer gesagt wird array beim Aufruf der Funktion in einen Zeiger auf 
das erste Element konvertiert.

> &array liefert die adresse des zeigers auf das erste element zurück,

Nein, tut es nicht, denn array ist kein Zeiger, sondern ein Array. 
Dementsprechend ist &array die Addresse des Arrays und nicht die eines 
Zeigers. Die Adresse des Arrays und seines ersten Elements sind zwar 
gleich, haben aber unterschiedliche Typen.

von DSP-Vision (Gast)


Lesenswert?

Hallo Markus,

ja, da liegst Du falsch. aes(array) ist korrekt (einfach ausprobieren). 
Die Ausdrücke
array und &array[0] sind identisch.

Beispiel:

void fkt(int *ptr, int i) ;
int array[10] ;

int main(int argc, char* argv[])
{
  fkt(&array[0], 2) ;
  for(int n=0 ; n< 10; n++)
  {
    printf("%d\n",array[n]) ;
  }
  getchar() ;
  return 0;
}

void fkt(int *ptr, int i)
{
  for(int n=0 ; n<10; n++){
    *ptr++ = n+i ;
  }
}

Gruß,
DSP-Vision

von arsh0r (Gast)


Lesenswert?

>> &array liefert die adresse des zeigers auf das erste element zurück,

>Nein, tut es nicht, denn array ist kein Zeiger, sondern ein Array.
>Dementsprechend ist &array die Addresse des Arrays und nicht die eines
>Zeigers. Die Adresse des Arrays und seines ersten Elements sind zwar
>gleich, haben aber unterschiedliche Typen.

also array und &array[0] ist dasselbe. aber ich hab immer gedacht das 
array und &array nicht dasselbe ist.

char array1[100];
char *array2;
array2 = (*char)malloc(100);

hab des imemr so verstanden das ein array nix anderes ist als ein zeiger 
dem von anfang an ein speicherbereich zugwewiesen wird. deshalb muss es 
einen zeiger geben der auf daas erste element im array zeigt und dessen 
adresse müsste man mit &array bekommen, oder bin ich grad voll auf dem 
holzweg...

von DSP-Vision (Gast)


Lesenswert?

mit
&array[0] bekommst Du die Adresse des ersten Elementes, mit
&array[3] die des dritten Elementes, u.s.w....

Du könntest also mit
  array2 = &array1[3]
dem Zeiger 2 die Adresse des dritten Elementes zuweisen (schön auf * , & 
und [] achten).

Gute Nacht!

von Karl H. (kbuchegg)


Lesenswert?

> hab des imemr so verstanden das ein array nix anderes ist als ein zeiger
> dem von anfang an ein speicherbereich zugwewiesen wird.

Dann hast du falsch gedacht.

Du hast 2 Möglichkeiten
* entweder du schreibst jetzt 100 mal:
  "Ein Array ist kein Zeiger. Ein Zeiger ist kein Array"

* oder du besorgst dir aus der Bibliothek möglichst schnell
  mal etwas Literatur zu´m Thema C. Kernighaen&Richie ist
  immer noch eine empfehlenswerte Literatur.

Wie Rolf weiter oben schon sagte: Unter bestimmten Umständen
wird ein Array zu einem Zeiger auf das erste Element des
Arrays konvertiert. Jedesmal wenn der Name des Arrays ohne
Indizierung vorkommt (mit ein paar kleinen Ausnahmen) ist
das der Fall.
Das bedeutet aber nicht, dass ein Array ein Zeiger ist!
Es wird nur bei Bedarf in einen konvertiert.

von Markus Reichert (Gast)


Lesenswert?

Vielen Dank für die vielen Antworten.

Jetzt weiß ich Bescheid und bin auch schon ein großes Stück 
weitergekommen.

Gruß
Markus

von Simon K. (simon) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:
>> hab des imemr so verstanden das ein array nix anderes ist als ein zeiger
>> dem von anfang an ein speicherbereich zugwewiesen wird.
>
> Dann hast du falsch gedacht.
>
> Du hast 2 Möglichkeiten
> * entweder du schreibst jetzt 100 mal:
>   "Ein Array ist kein Zeiger. Ein Zeiger ist kein Array"
>
> * oder du besorgst dir aus der Bibliothek möglichst schnell
>   mal etwas Literatur zu´m Thema C. Kernighaen&Richie ist
>   immer noch eine empfehlenswerte Literatur.
>
> Wie Rolf weiter oben schon sagte: Unter bestimmten Umständen
> wird ein Array zu einem Zeiger auf das erste Element des
> Arrays konvertiert. Jedesmal wenn der Name des Arrays ohne
> Indizierung vorkommt (mit ein paar kleinen Ausnahmen) ist
> das der Fall.
> Das bedeutet aber nicht, dass ein Array ein Zeiger ist!
> Es wird nur bei Bedarf in einen konvertiert.


Oha, wo wir gerade dabei sind. Bei welchem Beispiel wird denn der Name 
nicht in einen Zeiger konvertiert?

Würde mich grad mal interessieren.

Vielen Dank.

von Rolf Magnus (Gast)


Lesenswert?

> Jedesmal wenn der Name des Arrays ohne Indizierung vorkommt (mit ein
> paar kleinen Ausnahmen) ist das der Fall.

Im Prinzip auch, wenn er mit Indizierung vorkommt.

von Rolf Magnus (Gast)


Lesenswert?

> Oha, wo wir gerade dabei sind. Bei welchem Beispiel wird denn der Name
> nicht in einen Zeiger konvertiert?

char c[100];
sizeof(c);

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

sizeof ist keine Funktion, sondern wird bereits während des Compilierens 
durch den resultierenden Wert ersetzt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rufus T. Firefly wrote:

> sizeof ist keine Funktion, sondern wird bereits während des
> Compilierens durch den resultierenden Wert ersetzt.

Die Rede war ja auch nicht nur von Funktionen.  Auch in vielen
anderen Kontexten (bspw. bei direkter Benutzung des Namens in
einem Ausdruck) erfolgt ja eine implizite Konvertierung in den
zugehörigen Zeiger.

von Karl heinz B. (kbucheg)


Lesenswert?

Rufus T. Firefly wrote:
> sizeof ist keine Funktion, sondern wird bereits während des Compilierens
> durch den resultierenden Wert ersetzt.

Wie ist das eigentlich bei C99?
Da müsste sizeof ja sowohl zur Compiletime als auch
zur Runtime ausgewertet werden können. (Hab lange bevor C99
auf C++ gewechselt, daher meine Wissenslücke).

Bsp:

  size_t foo( int i )
  {
     int test[i];

     return sizeof( test );
  }

Ist ja seit C99 erlaubt. Oder darf man von solch 'dynamischen'
Typen keinen sizeof machen (kann ich mir aber nicht vorstellen).


von Marko B. (glagnar)


Lesenswert?

> Oha, wo wir gerade dabei sind. Bei welchem Beispiel wird denn der Name
> nicht in einen Zeiger konvertiert?

Versuch mal das:
1
char string[] = "foo";
2
3
string++;

und anschließend das:
1
char * string = "foo";
2
3
string++;

Du wirst einen Unterschied feststellen.

von Karl heinz B. (kbucheg)


Lesenswert?

> Versuch mal das:

Dieses Beispiel ist nicht ganz zulässig.
Im ersten Beispiel ist nämlich der Pointertyp auf den
der char string[] konvertiert wird, ein
  char * const

und damit ist klar, dass ein ++ auf diesen Pointer einen
Fehler ergeben muss.

von Marko B. (glagnar)


Lesenswert?

Ja, das wollte ich damit ausdrücken. Beim ersten Beispiel gibts eine 
Fehlermeldung, denn Arrays werden implizit zu *const konvertiert. 
Deshalb kann man mit Arrays keine Pointerarithmetik machen.

von Rolf Magnus (Gast)


Lesenswert?

@Karl Heinz:

In dem von dir angesprochenen Fall wird in C99 sizeof tatsächlich erst
zur Laufzeit ausgewertet. Die Norm selbst formuliert das so:

  6.5.3.4 The sizeof operator
  Constraints
[...]
2
The sizeof operator yields the size (in bytes) of its operand, which
may be an expression or the parenthesized name of a type. The size is 
determined from the type of the operand. The result is an integer. If 
the
type of the operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the result is an
integer constant.


Hier noch was zur impliziten Konvertierung von Arrays in Zeiger:

6.3.2.1 Lvalues, arrays, and function designators
[...]
3
Except when it is the operand of the sizeof operator or the unary & 
operator, or is a string literal used to initialize an array, an 
expression that has type ‘‘array of type’’ is converted to an expression 
with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue. If the array object has register 
storage class, the behavior is undefined.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.