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.
1 | short i = 306; |
2 | char *pi = (char*)&i; |
Wo jetzt High- und Lowbyte sind, hänget von der Endianess deines Systems.
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.
Peter P. schrieb: > . Nur das Zugreifen mit dem Pointer macht mir halt Probleme. Super. Zeig den restlichen Code und ich ergänze das gerne.
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 :)
Peter P. schrieb: > short i = 306; > char *ptr = &i; Das muss eine Warnung geben. Wenn nicht, dann pass den Warnlevel entsprechend an.
Karl schrieb: > Was ist eigentlich der Sinn eines Pointers? Damit man von verchiedenen Stellen aud dieselben Daten zugreifen kann.
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 ^^
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.
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++.
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)
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.
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?
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.
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)
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.
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.
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.
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.
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.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.