mikrocontroller.net

Forum: Compiler & IDEs pointer in struct / initialisierung / zugriff


Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
folgende definitionen / initalisierung:

typedef struct {
  CHAR cTest[5 + 1];
} T_TEST;

T_TEST xTestA[] = {
  {"12345"},
};

T_TEST xTestB[] = {
  {"67890"},
  {"55555"},
};

typedef struct {
  UCHAR ucKey;
  T_TEST *pTest;
} T_TEST_TBL;

T_TEST_TBL xTestTbl[] = {
  {1, (T_TEST *)&xTestA},
  {2, (T_TEST *)&xTestB}
}

wie kann ich nun zb. in einer schleife strlen von cTest aller elemente 
von xTestTbl ausgeben, dh:

KEY -> CTEST -> LEN
1 -> 12345 -> 6
2 -> 67890 -> 6
2 -> 55555 -> 6

danke

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LEN natürlich 5 ;)

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

Bewertung
0 lesenswert
nicht lesenswert
gert wrote:

> T_TEST_TBL xTestTbl[] = {
>   {1, (T_TEST *)&xTestA},
>   {2, (T_TEST *)&xTestB}
> }

Die Typecasts sind überflüssig.

> wie kann ich nun zb. in einer schleife strlen von cTest aller elemente
> von xTestTbl ausgeben, dh:

Gar nicht.  Du hast Tabellen dynamischer Größe, hast aber weder deren
Länge irgendwo festgehalten noch ein Endekennzeichen in jeder Tabelle
hinterlassen.  Damit kann man beim Blick ,,von oben'' nicht mehr
wissen, auf wie viele Tabellenelemente der jeweilige Zeiger nun wirklich
zeigt.

p.s.: Bitte Code-Markierungen benutzen.

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok dann mit counter - typecast brauche ich, sonst schreit compiler
typedef struct {
  CHAR cTest[5 + 1];
} T_TEST;

T_TEST xTestA[] = {
  {"12345"},
};

T_TEST xTestB[] = {
  {"67890"},
  {"55555"},
};

typedef struct {
  UCHAR ucKey;
  UCHAR ucCnt;
  T_TEST *pTest;
} T_TEST_TBL;

T_TEST_TBL xTestTbl[] = {
  {1, sizeof(xTestA)/sizeof(T_TEST), (T_TEST *)&xTestA},
  {2, sizeof(xTestB)/sizeof(T_TEST), (T_TEST *)&xTestB}


Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja geht auch ohne typecast
T_TEST_TBL xTestTbl[] = {
  {1, sizeof(xTestA)/sizeof(T_TEST), xTestA},
  {2, sizeof(xTestB)/sizeof(T_TEST), xTestB}
};

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int i,ii;

for (i=0;i<sizeof(xTestTbl)/sizeof(T_TEST_TBL);++i)
  for (ii=0;ii<xTestTbl[i].ucCnt;++ii)
      printf ("%d -> %s -> %d\n",
              xTestTbl[i].ucKey,
              xTestTbl[i].pTest[ii].cTest,
              strlen(xTestTbl[i].pTest[ii].cTest));

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke so hab ichs auch gemacht - nun habe ich den fehler gefunden:
T_TEST xTestA[] = {
  {"12345"},
};

wurde immer mit 0 initialisiert und nicht "12345"

habe umgeschrieben auf:
static const T_TEST xTestA[] = {
  {"12345"},
};

dann plötzlich wurde richtig initialisiert ???

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist compiler/sdk spezifisch

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ist compiler/sdk spezifisch

warum sollte das so sein? C ist C, das muß erst einmal jeder Compiler 
gleich verstehen.

Mich stört zwar das Komma am Ende von "{"12345"},", aber den Compiler 
anscheinend nicht. Funktionieren sollte die erste Variante auch.

Ich hab hiermit ein Problem:
T_TEST_TBL xTestTbl[] = {
{1, (T_TEST *)&xTestA},
{2, (T_TEST *)&xTestB}
}
&xTestA ist KEIN T_TEST*, sondern ein T_TEST**, deshalb hast du wohl 
auch die (eigentlich überflüssigen) Typecasts eingefügt. Gemeint ist 
wohl:
T_TEST_TBL xTestTbl[] = {
  {1, xTestA},
  {2, xTestB}
};


Oliver

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

Bewertung
0 lesenswert
nicht lesenswert
Oliver wrote:

> &xTestA ist KEIN T_TEST*, sondern ein T_TEST**

Nein, die Adresse eines Arrays ist die Adresse seines ersten Elements.

Überflüssig ist das & natürlich trotzdem, und es deutet darauf hin,
dass derjenige, der es geschrieben hat, die ganze Pointer&Array-
Geschichte noch nicht verstanden hat, sondern trial&error benutzt.

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habs eh ohne cast gemacht, es war nur zuerst das const drinnen und 
der compiler hat bei der initialisierung natürlich gemeckert (looses 
const qualifier)

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zur info : (T_TEST *)&xTestA == xTestA

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gert wrote:
> looses const qualifier
Ja zu Recht! Und anstatt deinen Fehler zu beheben, benutzt du die 
Allzweckwaffe Cast um die Symptome zu vertuschen. TZTZTZ!

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das war nur für einen schnellen test...
ok &xTestA[0] == xTestA

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> &xTestA ist KEIN T_TEST*, sondern ein T_TEST**
>
> Nein, die Adresse eines Arrays ist die Adresse seines ersten
> Elements.

Der numerische Wert von &xTestA und xTestA ist zwar der gleiche, der
Datentyp aber ein anderer:

xTestA ist ein T_TEST-Array und somit vom Typ T_TEST[] bzw. T_TEST[1].
Es kann verwendet werden wie ein konstanter Zeiger auf das erste
Element, also wie ein T_TEST*.

&xTestA hingegen ist ein Zeiger auf ein T_TEST-Array (nicht auf das
erste Element) und somit vom Typ T_TEST(*)[] bzw. T_TEST(*)[1]. Für
diesen Datentyp gibt es im vorliegenden Programm aber keine sinnvolle
Verwendung.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und damit du das const nicht weg-casten musst (was übrigens 
programmiertechnisch eine ziemliche Schweinerei ist!), musst du folgende 
Definition ändern:
typedef struct {
  UCHAR ucKey;
  const T_TEST *pTest; /* Zeiger auf ein konstantes T_TEST */
} T_TEST_TBL;

Autor: A. N. (netbandit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moment mal... xTestA ist doch ein Array (T_TEST*), also steht in xTestA 
die Adresse des ersten Elementes des Arrays.

Um den Wert dieses Elementes zu ändern kann ich
*xTestA oder xTestA[0] benutzen.

Wenn ich &xTestA schreibe bekomme ich die Adresse des Zeigers, der auf 
die Adresse des ersten Elementes des Arrays zeigt.. also durchaus ein 
T_TEST**

Oder hab ich da was nicht ganz verstanden?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Moment mal... xTestA ist doch ein Array

Bis hierher ist es richtig.

> (T_TEST*),

T_TEST* ist kein Array, sondern ein Zeiger. Array-Variablen können
zwar in vielen Kontexten wie Zeiger benutzt werden, trotzdem sind das
zwei unterschiedliche Dinge. So hat bspw. ein Zeiger die Größe einer
Adresse auf dem Zielsystem, die Größe eines Arrays hängt von der
Anzahl und der Größe der Elemente ab. Einer Zeigervariable kann
ein Wert zugewiesen werden, einer Arrayvariable nicht (nur deren
Elementen).

> also steht in xTestA die Adresse des ersten Elementes des Arrays.

Nein, in xTestA stehen die Arrayemelente. Erst wenn man bspw. p=xTestA
schreibt, wird xTestA durch die Adresse des ersten Elements ersetzt
und p zugewiesen.

> Um den Wert dieses Elementes zu ändern kann ich *xTestA oder
> xTestA[0] benutzen.

Richtig.

> Wenn ich &xTestA schreibe bekomme ich die Adresse des Zeigers, der
> auf die Adresse des ersten Elementes des Arrays zeigt.. also
> durchaus ein T_TEST**

Nein, das ist einer der Fälle, wo xTestA nicht durch einen Zeiger
auf das erste Elemente ersetzt wird, sondern ein Array bleibt. Somit
ist &xTestA kein Zeiger auf einen Zeiger das erste Element (T_TEST**),
sondern ein Zeiger auf das ganze Array(T_TEST(*)[] oder T_TEST(*[1]).
Wie schon oben geschrieben sind diese beiden Zeiger numerisch
natürlich gleich, trotzdem sind es aber zwei unterschiedliche
Datentypen.

> Oder hab ich da was nicht ganz verstanden?

Jetzt hoffentlich schon ;-)

Autor: A. N. (netbandit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ja, diese Sonderrolle der statischen Arrays war mir nicht bewusst. 
Ich dachte bis jetzt immer, dass "int a[5];" dazu führt, dass ein 
konstanter Zeiger auf ein Integer mit dem Namen a angelegt wird, 5 mal 
ein Integer im Speicher reserviert wird und die Adresse des ersten 
Integers in a gespeichert wird.
Also so wie man es dynamisch machen würde, nur dass halt der Compiler 
die Arbeit erledigt.

Man lernt nie aus, danke yalu!

Ganz durchdacht finde ich die Sache dann allerdings nicht. Wenn es hier 
also eh einen eigenen Datentypen gibt und sizeof(a) sogar die komplette 
Arraygröße zurückliefert, dann hätte man doch in die Compiler auch noch 
eine Bereichsprüfung für den [] Operator einbauen können, so dass bei 
statischen Arrays eben a[5] = ... nicht mehr möglich ist.

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

Bewertung
0 lesenswert
nicht lesenswert
A. N. wrote:

> Ganz durchdacht finde ich die Sache dann allerdings nicht. Wenn es hier
> also eh einen eigenen Datentypen gibt und sizeof(a) sogar die komplette
> Arraygröße zurückliefert, dann hätte man doch in die Compiler auch noch
> eine Bereichsprüfung für den [] Operator einbauen können, so dass bei
> statischen Arrays eben a[5] = ... nicht mehr möglich ist.

C besitzt von der Sprachdefinition einfach mal kein Laufzeitsystem,
was derartige Überprüfungen hergeben könnte (anders als bspw. Pascal).
Allerdings verbietet der Standard einer Implementierung nicht, ein
derartiges Feature anzubieten.  Es wird nur in der Regel nicht gemacht,
weil es einfach Performance kostet.

Autor: A. N. (netbandit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja das zur Laufzeit ist mir schon klar, aber wenigstens bei 
offensichtlichen Bereichsüberschreitungen müsste der Compiler beim 
Compelieren meckern.
z.B.
a[5] = 1;
bei nur 5 Elementen im Array.

Aber egal, hier ging es ja um ein anderes Thema :)

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Simon:

das mit dem const zeiger hatte ich schon hinzugefügt bei mir - danke 
trotzdem ;)
const T_TEST *pTest;

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.