Forum: Compiler & IDEs EIn cast auf (BYTE*) bei einer größeren Variable


von Simon (Gast)


Lesenswert?

Ich dachte bisher das ist so:

Wenn man auf ein BYTE zeigen möchte wählt man auch einen pointer der 
BYTE größe hat.

soll es was größeres sein z.B. UINT_32 dann auch einen UINT_32 pointer 
um bei beidarf mit pointer++ um eine variable weiter springen zu können.

Wie kann jedoch das hier sein:
1
typedef struct __attribute__((__packed__)) appConfigStruct 
2
{
3
  IP_ADDR    MyIPAddr;               // IP address
4
  IP_ADDR    MyMask;                 // Subnet mask
5
  IP_ADDR    MyGateway;              // Default Gateway
6
  IP_ADDR    PrimaryDNSServer;       // Primary DNS Server
7
  IP_ADDR    SecondaryDNSServer;     // Secondary DNS Server
8
  IP_ADDR    DefaultIPAddr;          // Default IP address
9
  IP_ADDR    DefaultMask;            // Default subnet mask
10
  BYTE    NetBIOSName[16];        // NetBIOS name
11
  struct
12
  {
13
    unsigned char : 6;
14
    unsigned char bIsDHCPEnabled : 1;
15
    unsigned char bInConfigMode : 1;
16
  } Flags;                            // Flag structure
17
  MAC_ADDR  MyMACAddr;              // Application MAC address
18
19
} APP_CONFIG;

Wie kann man hier, eine doch so große structure mit vielen variablen, 
mit nur einem byte pointer casten?
1
wOriginalAppConfigChecksum = CalcIPChecksum((BYTE*)&AppConfig, sizeof(AppConfig));

von Max (Gast)


Lesenswert?

Ist AppConfig in
1
wOriginalAppConfigChecksum = CalcIPChecksum((BYTE*)&AppConfig, sizeof(AppConfig));

auch wirklich eine Variable der Struktur APP_CONFIG?

von Rolf Magnus (Gast)


Lesenswert?

Simon schrieb:
> Wie kann man hier, eine doch so große structure mit vielen variablen,
> mit nur einem byte pointer casten?

Nicht die Variable wird gecastet, sondern ihre Adresse. Man erhält 
dann einen Pointer auf das erste Byte der Variable.

von Oliver (Gast)


Lesenswert?

Simon schrieb:
> Wenn man auf ein BYTE zeigen möchte wählt man auch einen pointer der
> BYTE größe hat.

Die pointer selber sind immer gleich groß, egal, auf was sie zeigen.

Oliver

von Simon (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Nicht die Variable wird gecastet, sondern ihre Adresse. Man erhält
> dann einen Pointer auf das erste Byte der Variable.

aaaah


Nur was wird dann aus dieser Adresse?
nehmen wir mal an &AppConfig ist 0xA000049C und was wird dann mit 
(BYTE*) gemacht?

von DirkB (Gast)


Lesenswert?

Mit der Adresse wird nichts gemacht.

Aber CalcIPChecksum erwartet einen BYTE*
&AppConfig ist aber ein APP_CONFIG*
Und das mag der Compiler nicht und warnt.

Mit dem cast sagst du dem Compiler: "Alles in Ordnung, ich weiß was ich 
tue"
(in der Hoffnung, dass das auch stimmt)

von Simon (Gast)


Lesenswert?

ah ok Danke.

Was würde passieren bei:
1
AppConfig++;

von (prx) A. K. (prx)


Lesenswert?

Fehlermeldung des Compilers.

von Simon (Gast)


Lesenswert?

Wie würde das richtig aussehen?


BYTE *x = &AppConfig;

x++;

?

Vorallem eh, was versuche ich da eigentlich? Auf das nächste AppConfig 
zu springen. müsste ich hier nicht irgendwas in der form von einem 
AppConfig[10] tun oder sowas?

von (prx) A. K. (prx)


Lesenswert?

Simon schrieb:
> BYTE *x = &AppConfig;
> x++;

Zeigt dann aufs 2. Byte von MyIPAddr.

> Auf das nächste AppConfig zu springen.

Das wäre im Prinzip erreicht mit

APP_CONFIG *p = &AppConfig;
p++;

Zeit dann allerdings in den Wald, weil AppConfig kein Array ist.

von Simon (Gast)


Lesenswert?

A. K. schrieb:
> APP_CONFIG *p = &AppConfig;


Wenn ich nun die Antworten zusammen fasse.

dann ist *p selbst immer gleich groß. und mit APP_CONFIG gebe ich vor um 
wieviel er weiterspringen muss?

von (prx) A. K. (prx)


Lesenswert?

Ja.

von DirkB (Gast)


Lesenswert?

Damit legst du auch fest, wieviel Byte beim Zugriff mit dem 
Dreferenzierungoperator gelesen/geschrieben werden.

von Rolf Magnus (Gast)


Lesenswert?

Simon schrieb:
> dann ist *p selbst immer gleich groß.

Nicht *p, sondern p. p ist der Zeiger, *p ist das, worauf er zeigt.

Simon schrieb:
> und mit APP_CONFIG gebe ich vor um wieviel er weiterspringen muss?

Generell woraus die Variable besteht und wie darauf zugegriffen werden 
muss. Auf Assembler-Ebene sind Zeiger in der Regel einfach Variablen, 
die halt eine Adresse enthalten. Was an der Adresse dann steht (also 
z.B. eine Zahl, ein Zeichen, eine weitere Adresse, eine Struktur, ...) 
muß der Programmierer sich quasi merken und selbst dafür sorgen, daß er 
den Wert an der Adresse nicht falsch interpretiert.
C ist dagegen eine typisierte Sprache, auch bei Zeigern, d.h. ein Zeiger 
enthält die Adresse, hat aber auch bei der Definition einen Typ 
bekommen, so daß der Compiler sich automatisch drum kümmern kann, den 
Zugriff richtig zu machen. Wenn du also einen Zeiger auf int namens p 
hast, dann ein *p machst, weiß der Compiler, daß er an der Adresse, auf 
die p zeigt, einen int zu erwarten hat und daher genau einen solchen da 
lesen muss.
Wenn nun eine Funktion sich nicht um die Datenstruktur kümmen, sondern 
die übergebenen Daten einfach als Speicherblock irgendeiner Größe 
interpretieren will, will sie einen Zeiger auf "bytes" haben, zusammen 
mit der Größe des Speicherblocks. Das heißt aber, daß du an die Funktion 
einen Zeiger auf einen anderen Typ übergibst, als sie eigentlich haben 
will. Damit der Compiler damit glücklich ist, mußt du ihm daher sagen 
"ja, ich weiß, daß der Typ anders ist, aber das ist in diesem Fall 
richtig so", und genau das tust du mit dem Cast (BYTE*).

von Oliver (Gast)


Lesenswert?

Simon schrieb:
> dann ist *p selbst immer gleich groß. und mit APP_CONFIG gebe ich vor um
> wieviel er weiterspringen muss?

Eigentlich legst du damit fest, auf was für einen Datentyp der pointer 
zeigt. Das beinhaltet dann auch die Information, um wieviele bytes der 
pointer bei ++ erhöht wird.

Kannst dir ja mal spasseshalber anschauen, was hier jeweils rauskommt:
1
uint8_t i = (uint8_t*) &AppConfig;
2
int j = (int*) &AppConfig;
3
uint64_t k = (uint64_t*) &AppConfig;
4
double l = (double*) &AppConfig;

und dann überlegen, warum...

Oliver

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
>> dann ist *p selbst immer gleich groß.
>
> Nicht *p, sondern p. p ist der Zeiger, *p ist das, worauf er zeigt.

Das worauf p zeigt ist immer gleich gross: sizeof(*p) liegt fest.

Er will vmtl. auf die Adressrechnung raus:
  (char *)p + sizeof(*p)
hat den gleichen Wert wie
  (char *)(p + 1)

: Bearbeitet durch User
von Rolf Magnus (Gast)


Lesenswert?

A. K. schrieb:
> Rolf Magnus schrieb:
>>> dann ist *p selbst immer gleich groß.
>>
>> Nicht *p, sondern p. p ist der Zeiger, *p ist das, worauf er zeigt.
>
> Das worauf p zeigt ist immer gleich gross: sizeof(*p) liegt fest.
> Er will vmtl. auf die Adressrechnung raus:
>   (char *)p + sizeof(*p)
> hat den gleichen Wert wie
>   (char *)(p + 1)

Ich hatte angenommen, daß er eher darauf hinaus will, daß die Größe 
eines Zeigers unabhängig von seinem Typ (eben "immer gleich") ist. Das 
muß zwar auch nicht unbedingt für jeden Zeigertyp gelten, tut es aber 
meist schon, zumindest bei Datenpointern.
*p, also das worauf er zeigt, ist dagegen vom Typ abhängig.
Also gilt:
1
struct A * a;
2
sturct B * b;
3
4
sizeof a == sizeof b;    // immer wahr
5
sizeof *a == sizeof *b;  // hängt von den Definitionen von A und B ab

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.