mikrocontroller.net

Forum: Compiler & IDEs Funktionsaufruf mit Zeiger


Autor: Markus Reichert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: arsh0r (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Robert (Gast)
Datum:

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

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: DSP-Vision (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: arsh0r (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: DSP-Vision (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Markus Reichert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die vielen Antworten.

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

Gruß
Markus

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

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

char c[100];
sizeof(c);

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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).


Autor: Marko B. (glagnar)
Datum:

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

Versuch mal das:
char string[] = "foo";

string++;

und anschließend das:
char * string = "foo";

string++;

Du wirst einen Unterschied feststellen.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Marko B. (glagnar)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.