Forum: Compiler & IDEs Highbyte und Lowbyte mit Pointer Anzeigen


von Peter P. (Gast)


Lesenswert?

Hallo Entschuldigung schonmal im Voraus falls das Thema bereits geklärt 
wurde, aber ich habe es nicht entdeckt.


Ich bin im Maschinenbaustudium und wir müssen für unser Fach ein 
bisschen mit C programmieren. Nun habe ich ein Problem die folgende 
Aufgabe zu lösen:


Schreiben Sie ein Programm, welches einer Short-
Variable (2 Bytes) den Wert 306 zuweist. Greifen Sie
anschließend mit einem Pointer das HighByte und das
LowByte zu und geben Sie diese auf dem Bildschirm
aus.

Da ich selber kaum programmieren kann und mir das einfach nicht in Kopf 
will wäre ich sehr erfreut, wenn mir hier jemand helfen könnte die 
Aufgabe zu lösen.

von Dirk B. (dirkb2)


Lesenswert?

1
short  i = 306;
2
char *pi = (char*)&i;
Wo jetzt High- und Lowbyte sind, hänget von der Endianess deines 
Systems.

von Peter P. (Gast)


Lesenswert?

Ja die Deklaration war bei mir nicht so das Problem. Das hätte ich 
vielleicht dazu schreiben sollen.

Dirk B. schrieb:
> Wo jetzt High- und Lowbyte sind, hänget von der Endianess deines
> Systems.

Und wie kann ich nun mit einem Pointer auf das High-/Lowbyte zugreifen 
und diese auf dem Bildschirm sichtbar machen? Bzw. Sichtbar machen kann 
ich ja nachher mit printf(). Nur das Zugreifen mit dem Pointer macht mir 
halt Probleme. Ich komme nicht auf einen Code, wie ich darauf zugreifen 
könnte.

von A. S. (Gast)


Lesenswert?

Peter P. schrieb:
> . Nur das Zugreifen mit dem Pointer macht mir halt Probleme.

Super. Zeig den restlichen Code und ich ergänze das gerne.

von Peter P. (Gast)


Lesenswert?

Hey ich danke euch für die Antworten. Habe jetzt bei nem Kommillitonen 
nachgefragt was der da haben wollte und habe jetzt das was unser Dozent 
von uns sehen wollte. Eigentlich total einfach. Wusste aber nicht das er 
das so simpel von uns sehen wollte.

Mein Code sieht mittlerweile aus:
1
short i = 306;
2
    char *ptr = &i;
3
    printf("Low-Byte: %d\n", *ptr);
4
    ptr++;
5
    printf("High-Byte: %d\n", *ptr);

Also total simpel.
Das Thema hat sich also damit erledigt. Ich danke trotzdem für die Hilfe 
:)

von Karl (Gast)


Lesenswert?

Was ist eigentlich der Sinn eines Pointers?

von Dirk B. (dirkb2)


Lesenswert?

Peter P. schrieb:
> short i = 306;
>     char *ptr = &i;

Das muss eine Warnung geben. Wenn nicht, dann pass den Warnlevel 
entsprechend an.

von Dirk B. (dirkb2)


Lesenswert?

Karl schrieb:
> Was ist eigentlich der Sinn eines Pointers?

Damit man von verchiedenen Stellen aud dieselben Daten zugreifen kann.

von Peter P. (Gast)


Lesenswert?

Dirk B. schrieb:
> Das muss eine Warnung geben. Wenn nicht, dann pass den Warnlevel
> entsprechend an.

Also wie schon gesagt ich kenne mich mit programmieren nicht aus. Und 
das ist halt die Lösung, die uns der Dozent gegeben hat. Ja gab eine 
Warnung aber wie ich den Warnlevel anpasse etc. weiß ich nicht. Wie 
gesagt ist das die Lösung unseres Dozenten und die gibt beim run des 
Programms das aus, was unser Dozent sehen möchte. Du musst bedenken, 
dass du hier jemandem Antwortest der ein kompletter Rookie ist und 
überhaupt keine Ahnung von nichts hat ^^

von PittyJ (Gast)


Lesenswert?

Karl schrieb:
> Was ist eigentlich der Sinn eines Pointers?

Ein Pointer ist wie ein Weblink. Man zitiert nicht den kompletten Text, 
sondern sagt, wo die Information steht.

von Dr. Sommer (Gast)


Lesenswert?

Peter P. schrieb:
> Wie gesagt ist das die Lösung unseres Dozenten und die gibt beim run des
> Programms das aus, was unser Dozent sehen möchte.

Dann führe das Programm mal auf einem Big Endian Rechner aus, z.B. einem 
alten Mac. Die Bytes werden vertauscht sein, denn das Verhalten des 
Programms hängt von der Plattform ab. Dieses Programm ist somit nicht 
korrekt. C erlaubt so etwas zwar (daher auch keine Warnung), aber das 
Ergebnis ist nicht garantiert. Bei negativen Zahlen würde sich das 
Ergebnis auch bei manchem Prozessoren unterscheiden, die sind aber 
ziemlich selten.

Die korrekte Art, Low&High Byte eines Signed Integer abzufragen ist gar 
nicht so einfach; man muss explizit das gewünschte Vorzeichenformat 
nachbilden. Die im Artikel Serialisierung gezeigte Bibliothek kann 
das, ist aber C++.

von Dirk B. (dirkb2)


Lesenswert?

Dr. Sommer schrieb:
> C erlaubt so etwas zwar (daher auch keine Warnung),

Doch eine Warnung. Die lautet etwa "Zuweisung eines char-Pointers an 
einen int-Pointer".
Da das hier aber gewünscht ist, hatte ich den cast gemacht.

Dr. Sommer schrieb:
> Die korrekte Art, Low&High Byte eines Signed Integer abzufragen ist gar
> nicht so einfach;

Mit dem Shift-Operator >> und verundung & ist es recht einfach.
1
    short i = 306; 
2
    char *ptr = &i;
3
    printf("Low-Byte: %d\n", (i        & 0xff));
4
    ptr++;
5
    printf("High-Byte: %d\n",((i >> 8) & 0xff));
und portabel. Da kommt bei Big- und Little Endianess dasselbe raus.

Der Compiler optimiert das schon (wenn er darf und der Prozessor 
Byteweisen Zugriff erlaubt)

von Dr. Sommer (Gast)


Lesenswert?

Dirk B. schrieb:
> Doch eine Warnung. Die lautet etwa "Zuweisung eines char-Pointers an
> einen int-Pointer".

Achja, man braucht den Cast. Es ist jedenfalls legal. Nur das Ergebnis 
ist eben nicht definiert.

Dirk B. schrieb:
> und portabel.

Nein, das Rechts-Shiften von vorzeichenbehafteten Typen wie "short" ist 
implementation defined. Es hängt vom Prozessor ab, ob das Sign-Bit mit 
geshiftet wird. Außerdem können verschiedene Prozessoren negative Zahlen 
unterschiedlich darstellen, weshalb die Bits anders sein können.

von Jemand (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Nein, das Rechts-Shiften von vorzeichenbehafteten Typen wie "short" ist
> implementation defined. Es hängt vom Prozessor ab, ob das Sign-Bit mit
> geshiftet wird.

Durch die Integer Promotion verschwindet das Sign-Bit doch sowieso aus 
den 16 Bit, oder nicht?

von Dr. Sommer (Gast)


Lesenswert?

Jemand schrieb:
> Durch die Integer Promotion verschwindet das Sign-Bit doch sowieso aus
> den 16 Bit, oder nicht?

Beim 2er-Komplement würde das den Wert ändern! Das Bit wird in die 
"neuen" 16bits kopiert (Sign Extension). Ist aber egal, denn 
Rechts-Shifts sind immer implementation-defined.

von Dirk B. (dirkb2)


Lesenswert?

Dr. Sommer schrieb:
> Es hängt vom Prozessor ab, ob das Sign-Bit mit
> geshiftet wird.

Es ist implementation defined wie aufgefüllt wird. Das spielt hier aber 
keine Rolle, da ja noch maskiert wird.

Zudem wird ja nicht die Archtitektur gewechselt (wie es bei der 
Serialisierung zum Datenaustausch passieren kann)

von Dr. Sommer (Gast)


Lesenswert?

Dirk B. schrieb:
> Das spielt hier aber
> keine Rolle, da ja noch maskiert wird.

Im Standard steht:
"The result of E1 >> E2 is E1 right-shifted E2 bit positions. [...] If 
E1 has a signed type and a negative value, the resulting value is 
implementation-defined."

Für mich heißt das, dass das Ergebnis immer implementation-defined ist. 
"i>>8" könnte also einfach immer 0 sein oder 42.

Die interessante Frage ist ja auch, ob das Ergebnis als vorzeichenloser 
8-Bit-Integer sein soll, oder auch vorzeichenbehaftet. Also ist das High 
Byte von -1234 vielleicht -4? Oder doch 252 (falls 2er-Komplement)? Oder 
251 (1er-Komplement)? Oder 132 (Sign-And-Magnitude)? Der C-Standard hat 
hier keine Vorgabe, weil das auf verschiedenen Plattformen 
unterschiedlich sein kann.

von Markus F. (mfro)


Lesenswert?

Dr. Sommer schrieb:
> Für mich heißt das, dass das Ergebnis immer implementation-defined ist.
> "i>>8" könnte also einfach immer 0 sein oder 42.

"Implementation Defined" heißt, daß irgendwo (z.B. im Handbuch) steht, 
wie die Operation durchgeführt wird, nicht daß "irgendwas" (oder auch 
mal 42 oder 0) rauskommt (das wäre "undefined").

Wenn man das Verhalten für "seine" unterstützte(n) Plattform(en) kennt 
und beachtet, spricht nichts dagegen, es zu benutzen.

von Dr. Sommer (Gast)


Lesenswert?

Markus F. schrieb:
> Wenn man das Verhalten für "seine" unterstützte(n) Plattform(en) kennt
> und beachtet, spricht nichts dagegen, es zu benutzen.

Ja. Aber dann kann man auch die Pointer-Version nehmen, denn deren 
Verhalten steht ebenso im Handbuch. Wenn man portablen Code schreiben 
möchte, geht das so halt nicht.

von Dirk B. (dirkb2)


Lesenswert?

Im Standard steht auch

3.4.1 implementation-defined behavior
unspecified behavior where each implementation documents how the choice 
is made
EXAMPLE An  example  of  implementation-defined  behavior  is  the 
propagation  of  the  high-order  bit when a signed integer is shifted 
right.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Markus F. schrieb:
> "Implementation Defined" heißt, daß irgendwo (z.B. im Handbuch) steht,
> wie die Operation durchgeführt wird, nicht daß "irgendwas" (oder auch
> mal 42 oder 0) rauskommt (das wäre "undefined").

Das "implementation defined" Verhalten muss einfach nur konsistent und 
dokumentiert sein, d.h. nicht von der Mondphase oder z.B. den 
Optimierungseinstellungen des Compilers abhängen. Wenn also der 
Hersteller schreibt: "Das Ergebnis der Rechtsschiebeoperation einer 
vorzeichenbehafteten Zahl ist 42, falls diese Zahl negativ ist.", ist 
das völlig in Ordnung.

Um bei dem konkreten Beispiel zu bleiben und eine Abgrenzung zu 
"undefined behaviour" durchzuführen: wenn z.B. eine vorzeichlose 
32-Bit-Variable um mehr als 32 Bit nach rechts geschoben wird, ist das 
Ergebnis entgegen der naiven Annahme nicht etwa immer Null, sondern 
nicht definiert. Folglich können auch alle weiteren Rechenschritte, die 
auf solch einem Ergebnis basieren, einfach ersatzlos wegoptimiert 
werden! Es gibt Compilerhersteller, die so etwas für besonders gute 
Ergebnisse bei Benchmarks einsetzen.

von Markus F. (mfro)


Lesenswert?

Andreas S. schrieb:
> Das "implementation defined" Verhalten muss einfach nur konsistent und
> dokumentiert sein, d.h. nicht von der Mondphase oder z.B. den
> Optimierungseinstellungen des Compilers abhängen.

Das könnte so sein, würde aber dem "höheren Gedanken" von 
"implementation defined" widersprechen. Das gibt's, damit der, der die 
Implementierung macht, die Freiheit hat, die für seine Plattform 
performanteste Variante zu nehmen.

Ich jedenfalls würde einem Compilerhersteller die 42 um die Ohren hauen 
und mich nach einem anderen umsehen.

Andreas S. schrieb:
> Folglich können auch alle weiteren Rechenschritte, die
> auf solch einem Ergebnis basieren, einfach ersatzlos wegoptimiert
> werden!

Da sind wir wieder bei der - m.E. rein philosophischen - Diskussion, ob 
ein Programm, das UB enthält, überhaupt starten oder irgendwas machen 
muß. Daran beteilige ich mich nicht.

UB ist ein Fehler und wer den in einem Benchmark macht, gehört 
(mindestens) geteert und gefedert.

von Rolf M. (rmagnus)


Lesenswert?

Markus F. schrieb:
> Wenn man das Verhalten für "seine" unterstützte(n) Plattform(en) kennt
> und beachtet,

... gilt das nicht mehr:

Dirk B. schrieb:
> und portabel.

Markus F. schrieb:
> Andreas S. schrieb:
>> Das "implementation defined" Verhalten muss einfach nur konsistent und
>> dokumentiert sein, d.h. nicht von der Mondphase oder z.B. den
>> Optimierungseinstellungen des Compilers abhängen.
>
> Das könnte so sein, würde aber dem "höheren Gedanken" von
> "implementation defined" widersprechen. Das gibt's, damit der, der die
> Implementierung macht, die Freiheit hat, die für seine Plattform
> performanteste Variante zu nehmen.

Allerdings muss das nicht unbedingt heißen, dass das zwingend eine von 
den zwei Möglichkeiten sein muss, die einem auf die Schnelle so in den 
Kopf schießen.

> UB ist ein Fehler und wer den in einem Benchmark macht, gehört
> (mindestens) geteert und gefedert.

Das ist dann allerdings ein Fehler des Benchmarks, nicht des Compilers.

von Heiko L. (zer0)


Lesenswert?

Rolf M. schrieb:
> Allerdings muss das nicht unbedingt heißen, dass das zwingend eine von
> den zwei Möglichkeiten sein muss, die einem auf die Schnelle so in den
> Kopf schießen.

Vor allem, was mit dem Paritätsbits passiert.
So gesehen ist eigentlich die Aufgabe überhaupt nicht zu beantworten, 
denn was sollen High- und LowByte denn schon bedeuten, wenn ein short 
auf einmal 17 oder 18 bit breit ist? "High" und "Low" - sind die 
Paritätsbits nun höherwertiger oder nicht? Da wird man auch mit 
Pointer-Zugriff nich weit kommen. Vielleicht liest man mit p[1] nur ein 
internes Loch für Padding aus und die hochwertigen Zahl-Bits stehen 
verteilt über p[3]-p[6].

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.