mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Feld Array Dynamisch Statisch Compiler C


Autor: maddin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe unten mal ein kleines c beispiel angehängt, in dem ein 2dim. 
feld auf 2 unterschiedliche arten un weisen angelegt wird, einmal 
statisch und einmal dynamisch.

wenn ein 2dim. feld statisch angelegt wird, dann liegen die zellen ja 
alle hintereinander im speicher :

feld[2][3];

speicher:
00
01
02
10
11
12

wenn das ganze jetzt dynamisch angelegt wird, dann kann man, so wie ich 
jetzt ja, vorerst speicher für ein eind. feld voller zeiger allokieren, 
die dann jeweils auf speicher zeigen indem die eigentlichen daten 
liegen, siehe bsp.:


#define DIMX 2
#define DIMX 3

voif function(void)
{
  int  x[DIMX][DIMY];
  int  **y;
  int i;

  y=(**int)malloc(DIMX*sizeof(*int));
  for (i=0; i<DIMX; i++)
  {
    y[i] =(*int)malloc(DIMY*sizeof(int));
  }
}

meine frage, wie bekommt der kompiler die umsetzung von :

g=x[1][2];
und
g=y[1][2];

auf die reihe, da dahinter ja eigentlich zwei völlig unterschiedliche 
strukturen:


y[c][d] entspricht *(*(y+a)+b)
x[c][d] entspricht *(x + (a*DIMY) + b)

liegen hin!?

m.

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

Bewertung
0 lesenswert
nicht lesenswert
maddin wrote:

<Im Prinzip korrekter Source Code. Die Syntax Fehler
 ignorieren wir mal. Du solltst dir aber abgewöhnen, den
 Returnwert von malloc zu casten.>

>
> meine frage, wie bekommt der kompiler die umsetzung von :
>
> g=x[1][2];
> und
> g=y[1][2];
>
> auf die reihe, da dahinter ja eigentlich zwei völlig unterschiedliche
> strukturen:

Der Compiler weiss aber, dass
x als 2-D Array definiert wurde

> x[c][d] entspricht *(x + (a*DIMY) + b)

Ganz genau. Das kann er Compiler aber nur machen, wenn
er weiss, dass x als
   T x[][]
angelegt wurde

> y[c][d] entspricht *(*(y+a)+b)

Yep.

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

Bewertung
0 lesenswert
nicht lesenswert
Man kanns auch so sehen (und so wird es der Compiler auch machen)

Die Ersetzung

    c[d]   <->  *(c + d)

gilt nur bei 'einfachen' Datentypen wie int, char, Pointer, etc.

Das Datentypergebnis von
   x[c]
ist aber, in deinem Fall,  int[]. Und damit kann diese
Äquivalenz nicht benutzt werden.

Autor: maddin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo KHB,
>> Du solltst dir aber abgewöhnen, den
 Returnwert von malloc zu casten<<

danke für den hinweis, auch wenn ich selbst in meinem "nur beispiel" 
nicht weis wo du dieses problem gefunden hast, habe ich das übersehen!?

>>Der Compiler weiss aber, dass
x als 2-D Array definiert wurde<<

das habe ich mir auch schon gedacht, compiler sind echt eine komplexe 
erfindung, ich bewundere immer wieder was alles möglich ist.

>>Ganz genau. Das kann er Compiler aber nur machen, wenn
er weiss, dass x als
   T x[][]
angelegt wurde<<

was meinst du mit T? ein struktur!?

gruß,
m.

Autor: maddin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
>>Man kanns auch so sehen (und so wird es der Compiler auch machen)

Die Ersetzung

    c[d]   <->  *(c + d)

gilt nur bei 'einfachen' Datentypen wie int, char, Pointer, etc.

Das Datentypergebnis von
   x[c]
ist aber, in deinem Fall,  int[]. Und damit kann diese
Äquivalenz nicht benutzt werden.<<

darüber muss ich einen moment grübeln.

m.

ps.: die sache mit dem c und d kam dadurch das ich es mit a und b hier 
nicht posten konnte da das forum der meinung war ich würde spam posten 
:-)

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

Bewertung
0 lesenswert
nicht lesenswert
maddin wrote:
> Hallo KHB,
>>> Du solltst dir aber abgewöhnen, den
>  Returnwert von malloc zu casten<<
>
> danke für den hinweis, auch wenn ich selbst in meinem "nur beispiel"
> nicht weis wo du dieses problem gefunden hast, habe ich das übersehen!?

zb. hier:

 y=(**int)malloc(DIMX*sizeof(*int));

(wenn wir mal von der falschen Pointer Syntax absehen)

Den Return Wert von malloc nie casten.
In C ist der cast unnötig. malloc liefert einen void* und
der ist in C zuweisungskompatibel zu allen Pointern.
Auf der anderen Seite kann dieser cast einen Fehler verstecken.
Nämlich dann, wenn kein Protoyp für malloc in Sicht ist.
Dann muss der Compiler laut C Regeln davon ausgehen, dass
malloc einen int zurückliefert. Ein int muss aber nicht
unbedingt dieselbe Größe wie ein Pointer haben. Ist der
cast nicht da, dann bemerkt das der Compiler und gibt einen
Fehler. Mit dem cast jedoch, wird das Typprüfsystem übergangen
und der Compiler akzeptiert diese Zuweisung wieder besseren Wissens.
Ein Cast ist immer eine Waffe! Man muss ihn weise und sparsam
einsetzen. Ist ein Cast unnötig, dann ist es immer besser
ihn wegzulassen.

Wenn dein Compiler aber ohne Cast meckert, dann ist das dann kein
C Compiler, sondern ein C++ Compiler. In dem Fall sollte man
aber malloc überhaupt nicht benutzen (es gibt auch Ausnahmen),
sondern stattdessen mit new arbeiten.

>
>>>Der Compiler weiss aber, dass
> x als 2-D Array definiert wurde<<
>
> das habe ich mir auch schon gedacht, compiler sind echt eine komplexe
> erfindung, ich bewundere immer wieder was alles möglich ist.
>
>>>Ganz genau. Das kann er Compiler aber nur machen, wenn
> er weiss, dass x als
>    T x[][]
> angelegt wurde<<
>
> was meinst du mit T? ein struktur!?

Ein Datentyp. T steht für die 'einfachen' Datentypen, wie
int, char, Pointer, float, double, struct ...

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

Bewertung
0 lesenswert
nicht lesenswert
maddin wrote:
>
> darüber muss ich einen moment grübeln.

Das ist wie in der Physik. Will man schnell abklären, ob eine
Formel grundsätzlich stimmen kann, dann vergleicht man einfach
die Einheiten.

  Bsp: Symbol   Bedeutung            Einheit
          s       Weg                m (Meter)
          t       Zeit               s (Sekunde)
          v       Geschwindigkeit    m/s
          a       Beschleunigung     m/s^2

   s = v * t

kann daher stimmen. Links steht als Einheit m. Rechts steht
als Einheit  m/s * s -> m. Auf beiden Seiten ergibt sich also
für die Einheit m

   s = v / t

kann daher nicht stimmen.
Linke Seite:   m
rechte Seite:  m/s / s -> m / s^2
Damit unterscheiden sich die linke und die rechte Seite in
den Einheiten und die Formel ist daher Quatsch

Ähnlich hier. Nur heist das nicht Einheit sondern Datentyp

  T * a;    (a ist ein Pointer auf T, T steht wieder für int,
             char, etc.)

  *a
da a ein Pointer auf T ist, ergibt *a das T selbst.
(int * b;      wenn b den Datentyp int* hat, dann hat *b den
               Datentyp int)

  T a[];

a ist ein Array von T. Ein einzelnes Element von A hat daher den
Datentyp T.

  T b[][];

b ist ein 2D Array von T. Eine Zeile des Arrays hat daher den
Typ  T[]. Ein einzelnes Element wiederrum davon hat den Typ T

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.