Forum: Compiler & IDEs Compiler Warnung


von Rene Z. (renezimmermann)


Lesenswert?

Hallo,

ich will gerade den TCP/IP Stack von Ulrich Radig kompilieren. Dabei 
erhalte ich mehrere Warnungen und weiss nicht so recht was das Problem 
ist.

Für Zeile:
1
(*((unsigned long*) &myip[0])) = get_eeprom_value(IP_EEPROM_STORE,MYIP);
erhalte ich die Warnung:
1
dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

1
extern unsigned char myip[4];
2
#define IP(a,b,c,d) ((unsigned long)(d)<<24)+((unsigned long)(c)<<16)+((unsigned long)(b)<<8)+a
3
#define MYIP    IP(192,168,1,88)
4
#define IP_EEPROM_STORE 30
1
unsigned long get_eeprom_value (unsigned int eeprom_adresse,unsigned long default_value)
2
{
3
  unsigned char value[4];
4
  
5
  for (unsigned char count = 0; count<4;count++)
6
  {
7
    eeprom_busy_wait ();  
8
    value[count] = eeprom_read_byte((unsigned char *)(eeprom_adresse + count));
9
  }
10
11
  //Ist der EEPROM Inhalt leer?
12
  if ((*((unsigned long*)&value[0])) == 0xFFFFFFFF)
13
  {
14
    return(default_value);
15
  }
16
  return((*((unsigned long*)&value[0])));
17
}

Ich verstehe das so:

Die Funktion "get_eeprom_value" holt die IP aus dem EEprom wenn dieser 
nicht leer ist. Ansonsten wird das Default Value zurückgegeben. Der 
Rückgabewert ist vom Typ unsigned long. Diese 4 Bytes sollen an die 
Adresse von myip[0] geschrieben werden. Es erfolgt ein Cast des unsigned 
char Zeigers auf einen unsigned long Zeiger. Mit dem ersten * soll dann 
der Wert dort gespeichert werden.

Aber was möchte mir der Compiler jetzt mitteilen und wie bekomme ich die 
Warnung weg?

Gruß Rene

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


Lesenswert?

Rene Zimmermann schrieb:
> Aber was möchte mir der Compiler jetzt mitteilen

Dass das wilde hin und her gecaste eines Zeigertyps ziemlicher
Pfusch ist.

> und wie bekomme ich die
> Warnung weg?

Indem man die vier Oktetts sauber einzeln aufbaut und
dann an myip[] zuweist.  Da sie aus dem EEPROM schon byteweise
gelesen werden, kann man natürlich einfach damit weiterarbeiten.
Man muss dann lediglich die vier Bytes einzeln gegen 0xFF vergleichen,
statt daraus fiktiv einen 32-bit-Integer zu fummeln, den man dann
der Faulheit halber gegen 0xFFFFFFFF vergleicht.

Der "unsigned long" darin hat ansonsten keinerlei Bedeutung, da
die vier gelesenen Bytes sowieso nicht zusammenhängend als eine
Zahl betrachtbar sind.  Schließlich stellt sich keiner hin
und sagt "meine IP-Adresse ist die 3232236289", sondern man sagt
stattdessen "meine IP-Adresse ist die 192.168.3.1".

von Rene Z. (renezimmermann)


Lesenswert?

Aha, also so.
1
    //(*((unsigned long*)&myip[0])) = get_eeprom_value(IP_EEPROM_STORE,MYIP);
2
  
3
  unsigned long temp = get_eeprom_value(IP_EEPROM_STORE,MYIP);
4
  myip[0] = (unsigned char) ((temp) >> 24);
5
  myip[1] = (unsigned char) ((temp) >> 16);
6
  myip[2] = (unsigned char) ((temp) >> 8);
7
  myip[3] = (unsigned char) (temp);

Gruß und Danke Rene

von Rene Z. (renezimmermann)


Lesenswert?

Und was vergessen:
1
unsigned long get_eeprom_value (unsigned int eeprom_adresse,unsigned long default_value)
2
{
3
  unsigned char value[4];
4
  
5
  for (unsigned char count = 0; count<4;count++)
6
  {
7
    eeprom_busy_wait ();  
8
    value[count] = eeprom_read_byte((unsigned char *)(eeprom_adresse + count));
9
  }
10
11
  //Ist der EEPROM Inhalt leer?
12
  if ((value[0] == 0xFF) && (value[1] == 0xFF) && (value[2] == 0xFF) && (value[3] == 0xFF)){
13
    return(default_value);
14
  }
15
  
16
  unsigned long temp = value[3];
17
  temp <<= 8;
18
  temp |= value[2];
19
  temp <<= 8;
20
  temp |= value[1];
21
  temp <<= 8;
22
  temp |= value[0];
23
  return temp;
24
}

Gruß

von Stefan E. (sternst)


Lesenswert?

1
unsigned long get_eeprom_value (unsigned int eeprom_adresse,unsigned long default_value)
2
{
3
  unsigned long value;
4
  
5
  value = eeprom_read_dword((unsigned long *)eeprom_adresse);
6
7
  //Ist der EEPROM Inhalt leer?
8
  if (value == 0xFFFFFFFF){
9
    return default_value;
10
  }
11
  
12
  return value;
13
}

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


Lesenswert?

Rene Zimmermann schrieb:
> Aha, also so.
>
>
1
    //(*((unsigned long*)&myip[0])) =
2
> get_eeprom_value(IP_EEPROM_STORE,MYIP);
3
> 
4
>   unsigned long temp = get_eeprom_value(IP_EEPROM_STORE,MYIP);

Nein.  Schmeiß das ganze "unsigned long"-Geraffel da raus.  Das hat
da nichts zu suchen.
1
extern unsigned char myip[4];
2
3
bool get_eeprom_ipaddr(unsigned int eeprom_adresse, unsigned char *addr)
4
{
5
  bool is_valid = true;
6
7
  for (unsigned char count = 0; count<4;count++)
8
  {
9
    eeprom_busy_wait ();
10
    unsigned char b = eeprom_read_byte((unsigned char *)(eeprom_adresse + count));
11
    if (is_valid && b == 0xff)
12
      is_valid = false;
13
    addr[count] = b;
14
  }
15
16
  return is_valid;
17
}
18
19
...
20
  if (!get_eeprom_ipaddr(IP_EEPROM_STORE, myip))
21
  {
22
    myip[0] = 192;
23
    myip[1] = 168;
24
    myip[2] = 1;
25
    myip[3] = 188;
26
  }

(Das mit der Default-Adresse kann man noch schöner schreiben, mir
ging's ums Prinzip mit dem get_eeprom_value().)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

1
  for (unsigned char count = 0; count<4;count++)
2
  {
3
    eeprom_busy_wait ();
4
    unsigned char b = eeprom_read_byte((unsigned char *)(eeprom_adresse + count));
5
    if (is_valid && b == 0xff)
6
      is_valid = false;
7
    addr[count] = b;
8
  }

Das ist aber problematisch, wenn eine IP-Adresse eine 255 enthält, was 
sie durchaus darf.
Einerseits, wenn diese "IP-Adresse" genutzt wird, um eine Subnet Mask zu 
speichern, andererseits aber auch direkt; 192.168.255.1 ist eine völlig 
legale Adresse.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wenn es nur darum geht, das Zeug irgendwie ohne Warnungen zu übersetzen 
und zum Laufen zu bekommen, geht -fno-strict-aliasing.

Das bedeutet dann, daß jeder Typ jeden anderen aliasen kann — entgegen 
den Aliasing-Regeln des C-Standards.

Damit muss man dann nicht (fremde) Quellen debuggen und von Hacks 
(zumindest nicht von diesem) säubern.

von Yalu X. (yalu) (Moderator)


Lesenswert?


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


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das ist aber problematisch, wenn eine IP-Adresse eine 255 enthält, was
> sie durchaus darf.

Hast natürlich recht, die Logik muss man ändern.
1
  uint8_t ff_seen = 0;
2
3
  ...
4
    if (b == 0xff) ff_seen++;
5
6
  ...
7
  return ff_seen < 4;

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:
> Rufus Τ. Firefly schrieb:
>> Das ist aber problematisch, wenn eine IP-Adresse eine 255 enthält, was
>> sie durchaus darf.
>
> Hast natürlich recht, die Logik muss man ändern.
>
>
1
>   uint8_t ff_seen = 0;
2
> 
3
>   ...
4
>     if (b == 0xff) ff_seen++;
5
> 
6
>   ...
7
>   return ff_seen < 4;
8
>

Entweder so, oder ganz einfach den Spiess umdrehen:
Sobald was anderes als 0xFF kommt, ist die IP gültig
1
bool get_eeprom_ipaddr(unsigned int eeprom_adresse, unsigned char *addr)
2
{
3
  bool is_valid = false;
4
5
  for (unsigned char count = 0; count<4;count++)
6
  {
7
    eeprom_busy_wait ();
8
    unsigned char b = eeprom_read_byte((unsigned char *)(eeprom_adresse + count));
9
    if (b != 0xff)
10
      is_valid = true;
11
    addr[count] = b;
12
  }
13
14
  return is_valid;
15
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Warum denn nicht ein eeprom_read_dword?

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.