Forum: Compiler & IDEs Ein paar kurze Fragen zu C


von mr.chip (Gast)


Lesenswert?

Hallo

Ich habe ein paar kurze Fragen zu C:

- Darf ich Signed-Variabeln als Array-Index verwenden? Wo gibt es hier 
gefahren (ausser, dass sie negativ werden könnten).

- Was passiert, wenn ich signed mit unsigned verrechne?

- Was passiert, wenn ich eine signed in eine unsigned caste?

Gruss

Michael

von Karl H. (kbuchegg)


Lesenswert?

ad 1
  Klar darfst du.
  Gefahren. Hmm. Es gibt da ein auf den ersten Blick merk-
  würdiges Verbot.
  Du darfst, wenn du ein Array der Länge n hast, die
  Adresse des Arrayelementes A[n] bilden. Du darfst nicht
  auf das Element zugreifen, da es nicht existiert, aber
  du darfst die Adresse davon bilden. Das gilts aber nicht
  in die andere Richtung. Du darfst nicht versuchen die
  Adresse des Arrayelementes A[-1] bilden. Schon alleine
  der Versuch diese Adresse zu bilden, ist illegal.
  Der Grund für ersteres ist leicht zu verstehen:

  Eine Schleife:
  for( i = 0; i < n; ++i )
    tu irgendwas mit A[i]

  wird gerne durch Pointerarithmetik ersetzt:

  for( tmp = A; tmp < &A[n]; ++tmp )
    tu irgendwas mit *tmp

  Nebeneffekt ist dabei, dass unmittelbar vor Schleifenabbruch
  tmp die Adresse von A[n] enthält.

  Will man aber das Array von der anderen Seite her abarbeiten

  for( i = n-1; i >= 0; --i )
    tu irgendwas mit A[i]

  kann man das nicht analog in Pointerarithmetik umpfriemeln

  for( tmp = &A[n-1]; tmp >= A; --tmp )
    tu irgendwas mit *tmp

  weil tmp am Ende den Wert &A[-1] annehmen würde, und alleine
  das Bilden dieses Wertes ist schon illegal.

ad 2
  Das ist dann ein signed unsigned mismatch. Wenn mich mein
  Gedächtnis nicht im Stich lässt, wird der signed Typ zum
  jeweils passenden unsigned Typ promoted.
  Wenn dein Rechner also 16 Bit 2-er Komplement Arithmetik
  benuzt, dann ist
     -1 > 33000U
  tatsächlich TRUE

ad 3
  Was soll passieren?
  Der Compiler ändert in der Berechnung den Datentyp.
  Aber abgesehen davon bleibt das Bitmuster unangetastet.
  Dasselbe Bitmuster das den signed Typ ausmacht wird dann
  als unsigned Typ interpretiert und damit weitergerechnet als
  ob es schon immer unsigned gewesen wäre.

von Peter D. (peda)


Lesenswert?

Karl heinz Buchegger wrote:

>   for( tmp = &A[n-1]; tmp >= A; --tmp )
>     tu irgendwas mit *tmp
>
>   weil tmp am Ende den Wert &A[-1] annehmen würde, und alleine
>   das Bilden dieses Wertes ist schon illegal.


Bei Harvard Architekturen (z.B. 8051) ist 0x0000 eine gültige Adresse 
und wird auch verwendet.
0x0000 - 1 ist dann 0xFFFF und die Schleife würde nie abgebrochen.


Allerdings kann das auch nach oben hin passieren, wenn der SRAM bis zum 
letzten Byte ausgequetscht würde.
Praktisch dürfte das kaum der Fall sein.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Hier gehts nicht um Harvard oder nicht Harvard.
Hier geht es darum, was dir der C-Standard zugesteht.
Und der gesteht dir nun mal zu, dass
   int A[5];

   int*  b = &A[5];
legal ist und ein definierstes Ergebnis hat.
Wohingegen
   b = &A[-1];

nicht legal ist.

> Allerdings kann das auch nach oben hin passieren, wenn der SRAM bis zum
> letzten Byte ausgequetscht würde.

Genau diesen Fall muss der Compiler verhindern. Der Compiler muss
das Array so legen, dass das nicht passiert. Er muss also
sicherstellen, dass für

    type A[N]

die Adresse &A[N] gebildet werden kann und dass &A[N] > &A[N-1]
ist.


von Karl H. (kbuchegg)


Lesenswert?

> Genau diesen Fall muss der Compiler verhindern

Nachtrag: Ob die meisten Compiler das wirklich tun, na ja, ich hab
da so meine Zweifel. Aber wenn er C-Standard konform ist,
müsste er.

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.