Forum: PC-Programmierung C Pointer Arithmetik - Integer Promotion


von Christian (Gast)


Lesenswert?

Hallo.

Ich möchte 2 Zeiger vom Typ uint32* miteinander subtrahieren. Das 
Ergebnis soll vom Typ uint32 sein:

uint32 Result;
uint32 *p1,*p2;

Result = p1 - p2;

Kann es sein, das die rechte Zuweisung zu signed int promoted wird? 
Misra Check sagt mir das ich signed int zu unsigned long zuweise(Misra 
Rule 10.3).

Gruß
Christian

von B. S. (bestucki)


Lesenswert?

Christian schrieb:
> Das Ergebnis soll vom Typ uint32 sein:

Warum? Für Differenzen von Zeigern gibt es einen eigenen Datentyp:
http://www.cplusplus.com/reference/cstddef/ptrdiff_t/

Christian schrieb:
> Kann es sein, das die rechte Zuweisung zu signed int promoted wird?

Überlege, was passieren würde, wenn die Operation unsigned durchgeführt 
würde und p2 grösser als p1 wäre. Würde dann folgendes Beispiel wie 
erwartet funktionieren?
1
int * p1, * p2, * i;
2
i += p1 - p2;

von Tom (Gast)


Lesenswert?


von Klaus (Gast)


Lesenswert?

Man müsste mal genauer wissen, wozu Du das machen willst.

Schon im K&R steht, dass Zeiger und integers nicht beliebig ineinander 
überführt werden können. Auch ist Arithmetik mit Zeigern nicht genauso 
unbeschränkt möglich, wie mit integers. Differenz ging und geht aber.
Vermutlich steht in den neueren C99, C11 etc. dazu auch etwas - 
vielleicht sogar in gewisser Hinsicht von K&R abweichend. Aber schon im 
K&R stand was von ptrdiff_t.

Das hilft nicht viel weiter, ich weiß. Soll aber heissen: Lies mal bitte 
nach.

von Buchwert (Gast)


Lesenswert?

Wer "... miteinander subtrahieren ..." schreibt, der weiß vielleicht 
nicht einmal selbst was er will. Die Operation ist weder auf der Ebene 
von Adressen, noch auf der Ebene von Zahlen sinnvoll.

von Peter II (Gast)


Lesenswert?

Buchwert schrieb:
> Die Operation ist weder auf der Ebene
> von Adressen, noch auf der Ebene von Zahlen sinnvoll.

doch ist sie. Wird auch sehr oft gebraucht.
1
int strlen( const char* s ) 
2
{
3
   const char* t = s;
4
   while ( *t ) { 
5
      t++;
6
   }
7
return t - s;
8
};

(klar kann man das auch anders Programmieren)

von Christian (Gast)


Lesenswert?

Wie im Beispiel oben sind p1 und p2 Zeiger auf 2 Speicherbereiche, deren 
Abstand mich interessiert. Daher die Subtraktion. Was mich interessiert 
ist,das das Ergebnis der Subtraktion implicit auf int gecastet wurde.

von Buchwert (Gast)


Lesenswert?

Peter II schrieb:
> Buchwert schrieb:
>> Die Operation ist weder auf der Ebene
>> von Adressen, noch auf der Ebene von Zahlen sinnvoll.
>
> doch ist sie. Wird auch sehr oft gebraucht.

Nicht von mir.

> (klar kann man das auch anders Programmieren)

Sollte man auch.

>

Es ist die Operation des TOs gemeint. Er bekommt nicht umsonst einen 
Rüffel von Misra.

von Peter II (Gast)


Lesenswert?

Buchwert schrieb:
> Sollte man auch.
warum?

Das ist gültiges und recht optimiertes C.

von B. S. (bestucki)


Lesenswert?

Christian schrieb:
> Wie im Beispiel oben sind p1 und p2 Zeiger auf 2 Speicherbereiche, deren
> Abstand mich interessiert.

Es dürfen nur Zeiger subtrahiert werden, die auf den gleichen 
Speicherbereich zeigen:

> When two pointers are subtracted, both shall point to elements of the
> same array object, or one past the last element of the array object;
> the result is the difference of the subscripts of the two array elements.
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

Das hat auch seinen Guten Grund:
1
//Annahme: sizeof(int) == 4
2
int * p1 = (int *)10;
3
int * p2 = (int *)20;
4
ptrdiff_t Result = p2 - p1; // Result ist 2
5
p1++; // p1 ist nun 14
6
Result = p2 - p1; // Result ist 1

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

be s. schrieb:
> Das hat auch seinen Guten Grund:

Oder bei segmentierter Adressierung:
  int *p1 = malloc(N1);
  int *p2 = malloc(N2);
  ptrdiff_t delta = p1 - p2;
Da kann je nach Laune delta==0 sein, obwohl p1!=p2.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Christian schrieb:
> Was mich interessiert
> ist,das das Ergebnis der Subtraktion implicit auf int gecastet wurde.

Wie schon geschrieben wurde, ist das Ergebnis zunächst mal vom Typ 
ptrdiff_t. Dieser ist laut C-Standard ein Synonym für einen 
implementationsabhängig definierten signed Integer-Typen - also 
vermutlich in den allermeisten Fällen ein typedef int. Signed deshalb, 
weil die Differenz ja auch negativ sein kann.

Oliver

von Mikro 7. (mikro77)


Lesenswert?

Yepp. Und hier noch der Auszug aus dem Standard:
1
When two pointers are subtracted, both shall point to elements of the same array object,
2
or one past the last element of the array object; the result is the difference of the
3
subscripts of the two array elements. The size of the result is implementation-defined,
4
and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header.
5
If the result is not representable in an object of that type, the behavior is undefined.

von (prx) A. K. (prx)


Lesenswert?

Oliver S. schrieb:
> vermutlich in den allermeisten Fällen ein typedef int.

Nein, da bei x86-64 die Pointer 64 Bits breit sind, "int" in den beiden 
verbreiteten Typmodellen aber trotz 64-Bit Maschine nur 32 Bits hat. Da 
ist dann "long" (Linux) oder "long long" (Windows) nötig.

: Bearbeitet durch User
von Ralf D. (rad)


Lesenswert?


: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

Christian schrieb:
> Hallo.
>
> Ich möchte 2 Zeiger vom Typ uint32* miteinander subtrahieren. Das
> Ergebnis soll vom Typ uint32 sein:
>
> uint32 Result;
> uint32 *p1,*p2;
>
> Result = p1 - p2;
>
> Kann es sein, das die rechte Zuweisung zu signed int promoted wird?
> Misra Check sagt mir das ich signed int zu unsigned long zuweise(Misra
> Rule 10.3).

Was willst Du erreichen?

Wenn Du MISRA-Regeln zu befolgen hast, dann schreibst Du wohl Code für 
ein Steuergerät oder dergleichen. Ich wüsste beim besten Willen keinen 
vernünftigen Grund, warum man da Zeiger voneinander subtrahieren sollte.

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.