expertenaustausch > comp.lang.* > comp.lang.c

Stefan Ram (09.06.2019, 14:45)
Zum Kurs

Das Programmieren mit der Programmiersprache C



wurde zum Kapitel 28 die Lektion 28.14

Adressen und Zahlen in C



hinzugefügt (auch erreichbar mit "http:").

Text der Lektion

Adressen und Zahlen in C

Wandlungen einer Adresse in eine Zahl

Eine Adresse kann grundsätzlich in eine Zahl gewandelt werden. Das
Ergebnis der Wandlung ist implementationsdefiniert. Falls der Zieltyp
das Ergebnis nicht darstellen kann, hat die Wandlung jedoch
undefiniertes Verhalten. Es ist nicht gesagt, daß es für jeden
Adreßtyp überhaupt irgendeinen Zahlentyp gibt, der seine Werte
darstellen kann.

N2310, 6.3.2.3p6
Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If
the result cannot be represented in the integer type, the
behavior is undefined. The result need not be in the range of
values of any integer type.

Damit verbietet sich solch eine Wandlung in portablem Code.

»uintptr_t« und »intptr_t«

Es ist jedoch erlaubt, eine void-Adresse in einen Wert des
vorzeichenlosen Zahlentyps »uintptr_t« oder des vorzeichenbehafteten
Zahlentyps »intptr_t« zu wandeln. Die Rückwandlung der erhaltenen
Zahlen in eine void-Adresse ergibt dann wieder die ursprünglich
Adresse.

Die beide Typen »uintptr_t« und »intptr_t« müssen jedoch nicht von
jeder C-Implementation implementiert werden. Damit kann man sich in
portablem Code auch nicht darauf verlassen, daß sie verfügbar sind.

Siehe auch
N2310, 7.20.1.4p1

Wandlungen einer Zahl in eine Adresse

Eine Zahl kann grundsätzlich in eine Adresse gewandelt werden. Das
Ergebnis ist (außer bei der Nullzeigerkonstanten »0«) jedoch
implementationsdefiniert. Es kann sein, daß der erhaltene Zeiger nicht
verwendbar ist.

N2310, 6.3.2.3p5
An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity of
the referenced type, and might be a trap representation.

Damit verbietet sich solch eine Wandlung in portablem Code.

»uintptr_t« und »intptr_t«

Selbst die Typen »uintptr_t« und »intptr_t« erlauben es im allgemeinen
nicht, eine beliebige Zahl in einen Zeiger zu verwandeln, der dann
verwendet werden darf.

Anwendbarkeit von Wandlungen zwischen Zahlen und Adressen

Wandlung zwischen Zeigern und Zahlen sind bei einzelnen
C-Implementationen möglich.

Bei speziellen C-Implementationen für Microcontroller kann man
beispielsweise durch Auswertung des folgenden Ausdrucks den Wert «7» in
den Speicher bei der Adresse «4096» schreiben.

Ausdruck

*( int * )4096 = 7

Literaturhinweis
Programming Microcontrollers in C ? Ted Van Sickle (2001),
Kapitel 3 ?Pointers?, Abschnitt ?Pointers and Multidimensional
Arrays? (in der zweiten Auflage von 2001)

In maximal portablem Code sind solche Wandlungen aber nicht möglich.
Rainer Weikusat (09.06.2019, 20:32)
ram (Stefan Ram) writes:

[...]

> Anwendbarkeit von Wandlungen zwischen Zahlen und Adressen
> Wandlung zwischen Zeigern und Zahlen sind bei einzelnen
> C-Implementationen möglich.
> Bei speziellen C-Implementationen für Microcontroller kann man
> beispielsweise durch Auswertung des folgenden Ausdrucks den Wert «7» in
> den Speicher bei der Adresse «4096» schreiben.
> Ausdruck
> *( int * )4096 = 7


Welchen Sinn hat es eigetlich, Studenten absichtlich die Unwahrheit zu
erzaehlen? Wandlungen zwischen Zahlen und Zeigern sind bei
C-Implementierungen normalerweise immer moeglich. Allerdings gibts es
(oder gab es) Hardware-Plattformen, wo das nicht oder nur eingeschraenkt
der Fall war. Typischerweise sind die veraltet.

Es gibt auch Versuche nervoeser Java-Programmierer, die normalerweise
fuer Google arbeiten, der Welt das als "Sicherheitsfeature" wieder
aufzuschwaetzen. Was daraus wird, bleibt abzuwarten.

---------
#include <sys/personality.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
if (personality(0xffffffff) != PER_SVR4) {
personality(PER_SVR4);
execvp(*argv, argv);
}

printf("%d\n", *(int *)0);

return 0;
}
--------

Ein Linux-Programm, das den Inhalt von Speicherstelle 0 ausgibt (braucht
privilegierte Aussfuehrung).
Rainer Weikusat (09.06.2019, 20:43)
Rainer Weikusat <rweikusat> writes:

[...]

> Es gibt auch Versuche nervoeser Java-Programmierer, die normalerweise
> fuer Google arbeiten, der Welt das als "Sicherheitsfeature" wieder
> aufzuschwaetzen. Was daraus wird, bleibt abzuwarten.


OT "Sicherheitsnachtrag": Richtige 'Hacker' (in der umgangsprachlichen
Bedeutung des Wortes) schreiben uebrigens auch keine irrsinnig
komplizierten Programme, um kompliziert irrsinnige
Speicherzugriffsschutzverfahren auszutricksen (obwohl das Leuten, die
ein Haendchen fuer sowas haben, mit schoener Regelmaessigkeit gelingt)
sondern die schicken 10.000 Emails des Inhaltes

"Hier spricht die Systemadministration. Bitte aendern Sie aus
Sicherheitgruenden ihr Passwort auf 'Idiot' und klicken Sie dann
untenstehenden Link"

und warten auf Anworten.
Bonita Montero (09.06.2019, 21:20)
Du solltest es besser sein lassen, anderen irgendwas beizubringen.
Denn Du schreibst so als würdest Du für dich selbst deine Gedanken
in zwanghadter Art ordnen wollen und verzettelst dich in für Anfänger
Praxis-irrelevante Fisematenten.
Stefan Reuther (10.06.2019, 11:10)
Am 09.06.2019 um 20:32 schrieb Rainer Weikusat:
> ram (Stefan Ram) writes:
> Welchen Sinn hat es eigetlich, Studenten absichtlich die Unwahrheit zu
> erzaehlen? Wandlungen zwischen Zahlen und Zeigern sind bei
> C-Implementierungen normalerweise immer moeglich. Allerdings gibts es
> (oder gab es) Hardware-Plattformen, wo das nicht oder nur eingeschraenkt
> der Fall war. Typischerweise sind die veraltet.


Das Schöne an C ist: man kann es auch auf veralteter Hardware betreiben...

> Es gibt auch Versuche nervoeser Java-Programmierer, die normalerweise
> fuer Google arbeiten, der Welt das als "Sicherheitsfeature" wieder
> aufzuschwaetzen. Was daraus wird, bleibt abzuwarten.


....im Gegensatz zu Java (oder Rust, oder Go, oder Python, oder...), wo
man unter 32 Bit (oder ohne von-Neumann-Architektur) gar nicht
anzutreten braucht.

Insofern trifft's das juristische "grundsätzlich" ganz gut: ja,
normalerweise geht das, aber es sind eben eine Menge Fußnoten zu
beachten, die man im Einführungstext erstmal übergeht. Und sei es die,
dass *(char*)0x00400017 auf gewissen Architekturen eben nicht auf die
lineare Adresse 0x00400017, sondern 0x00417 zugreift.

Eine "neue" "Architektur", auf der das mit den Pointern knifflig wird,
ist übrigens emscripten. Da haben Funktionszeiger erstmal keine direkte
Repräsentation als Zahl.

Stefan
Rainer Weikusat (10.06.2019, 16:25)
Stefan Reuther <stefan.news> writes:
> Am 09.06.2019 um 20:32 schrieb Rainer Weikusat:
> Das Schöne an C ist: man kann es auch auf veralteter Hardware betreiben...


.... und? Mein Arbeitgeber bezahlt mich nicht dafuer, Code zu schreiben,
der im x86 real mode laufen wuerde, damit er das tut.

> ...im Gegensatz zu Java (oder Rust, oder Go, oder Python, oder...), wo
> man unter 32 Bit (oder ohne von-Neumann-Architektur) gar nicht
> anzutreten braucht.
> Insofern trifft's das juristische "grundsätzlich" ganz gut: ja,
> normalerweise geht das, aber es sind eben eine Menge Fußnoten zu
> beachten, die man im Einführungstext erstmal übergeht.


Es stellt allerdings des Thema von Fuessen auf den Kopf: Wie bei allen
anderen Typen macht C auch bei Zeigern nur sehr allgemeine, funktionale
Vorgaben. Das soll es ermoeglichen, moeglichst viel von C auch auf
exotischen Plattformen benutzen zu koennen. Das waere ein gutes
Anschlussthema fuer Fortgeschrittene, die den verbreitetsten Fall
bereits beherrschen.

[...]

> Eine "neue" "Architektur", auf der das mit den Pointern knifflig wird,
> ist übrigens emscripten. Da haben Funktionszeiger erstmal keine direkte
> Repräsentation als Zahl.


Keine bloede Idee aus der Vergangenheit ist so bloed, dass sie im
"Computer Science"-Bereich konsequent zu einem vielleicht historisch
interessanten Anschaungsobjekt reduziert werden wuerde, solange sich
noch jemand findet, der sie noch nicht kennt und dem man sie deswegen
als 'moderne Innovation' verkaufen kann :->.
Thomas Koenig (10.06.2019, 16:57)
Rainer Weikusat <rweikusat> schrieb:

> Mein Arbeitgeber bezahlt mich nicht dafuer, Code zu schreiben,
> der im x86 real mode laufen wuerde, damit er das tut.

^~~
(1)

Warning: "das" is used unitialized in this context at (1) [-Wsemantic-context]
Rainer Weikusat (10.06.2019, 18:14)
Thomas Koenig <tkoenig> writes:
> Rainer Weikusat <rweikusat> schrieb:
>> Mein Arbeitgeber bezahlt mich nicht dafuer, Code zu schreiben,
>> der im x86 real mode laufen wuerde, damit er das tut.

> ^~~
> (1)
> Warning: "das" is used unitialized in this context at (1) [-Wsemantic-context]


Finde ich nicht.
Bonita Montero (10.06.2019, 19:09)
> Insofern trifft's das juristische "grundsätzlich" ganz gut: ja,
> normalerweise geht das, aber es sind eben eine Menge Fußnoten zu
> beachten, die man im Einführungstext erstmal übergeht. Und sei es
> die, dass *(char*)0x00400017 auf gewissen Architekturen eben nicht
> auf die lineare Adresse 0x00400017, sondern 0x00417 zugreift.


Hast vielleicht mal drüber nachgedacht, dass das ohnehin völlig latte
ist weil das auf keiner weiteren Architektur als der mit dem jeweili-
gen Hardware-Register Sinn ergibt?
Oder mit anderen Worten: Du verzettelst dich in Kleinigkeiten ohne
das große Ganze zu sehen.
Stefan Reuther (11.06.2019, 17:42)
Am 10.06.2019 um 16:25 schrieb Rainer Weikusat:
> Stefan Reuther <stefan.news> writes:
> ... und? Mein Arbeitgeber bezahlt mich nicht dafuer, Code zu schreiben,
> der im x86 real mode laufen wuerde, damit er das tut.


Daraus, wofür dein Arbeitgeber dich bezahlt (oder meiner mich) folgt so
ziemlich genau gar nix darüber, wofür andere Arbeitgeber andere Leute
zahlen, oder für die Sprache C im Allgemeinen.

Das ist ein Unterschied zu von Unternehmen gepflegten Sprachen wie Go,
C# oder Delphi. Die können das, was der entsprechende Arbeitgeber gerade
braucht. Borland brauchte "dynamische Methoden" zum Dispatchen von
Windows-Messages? Ab in den Compiler damit.

> Es stellt allerdings des Thema von Fuessen auf den Kopf: Wie bei allen
> anderen Typen macht C auch bei Zeigern nur sehr allgemeine, funktionale
> Vorgaben. Das soll es ermoeglichen, moeglichst viel von C auch auf
> exotischen Plattformen benutzen zu koennen. Das waere ein gutes
> Anschlussthema fuer Fortgeschrittene, die den verbreitetsten Fall
> bereits beherrschen.


Man kann einen Einführungstext auch ganz gut verfassen, ohne zu
beschreiben, dass Zeiger von und in Zahlen konvertiert werden können.
Insofern würde ich sagen: wer mit der Repräsentation von Zeigern als
Bitmuster anfängt, stellt das Thema von den Füßen auf den Kopf.

> Keine bloede Idee aus der Vergangenheit ist so bloed, dass sie im
> "Computer Science"-Bereich konsequent zu einem vielleicht historisch
> interessanten Anschaungsobjekt reduziert werden wuerde, solange sich
> noch jemand findet, der sie noch nicht kennt und dem man sie deswegen
> als 'moderne Innovation' verkaufen kann :->.


Ich weiß zwar nicht, was du damit aussagen willst, aber emscripten ist
eben nicht alt, und die Tatsache, dass (Funktions)Zeiger in JavaScript
nicht einfach so aus Zahlen konstruiert werden können, ist Bestandteil
des VM-Sicherheitskonzeptes: Abschottung von Komponenten gegeneinander
ohne zwingende Hardware-Unterstützung dafür. Das finde ich durchaus
innovativ.

Stefan
Helmut Schellong (11.06.2019, 19:29)
On 06/11/2019 17:42, Stefan Reuther wrote:
> Am 10.06.2019 um 16:25 schrieb Rainer Weikusat:


> Man kann einen Einführungstext auch ganz gut verfassen, ohne zu
> beschreiben, dass Zeiger von und in Zahlen konvertiert werden können.
> Insofern würde ich sagen: wer mit der Repräsentation von Zeigern als
> Bitmuster anfängt, stellt das Thema von den Füßen auf den Kopf.


Interessant ist, daß auf fast allen Plattformen eine
Konversion gar nicht stattfindet:
Konversions-Algorithmus: ;
Jede Adresse ist halt eine normale Integer-Zahl.
Beispielsweise kann das Register eax nacheinander
gemischt Integer mit Integer-Semantik und Adressen-Semantik
enthalten, und nach Dereferenzierung zum Schluß eine Adresse
unverändert an printf() übergeben.

Daß der C-Standard von einer Konversion schreibt, ist logisch.
Denn eine nicht-leere Konversion kann auch mal notwendig sein.
Rainer Weikusat (12.06.2019, 00:20)
Stefan Reuther <stefan.news> writes:
> Am 10.06.2019 um 16:25 schrieb Rainer Weikusat:
> Daraus, wofür dein Arbeitgeber dich bezahlt (oder meiner mich) folgt so
> ziemlich genau gar nix darüber, wofür andere Arbeitgeber andere Leute
> zahlen, oder für die Sprache C im Allgemeinen.


Daraus folgt, dass es gute Gruende gibt, sich um diese "veraltete
Hardware" nicht zu kuemmern.

[Zeigerrepraesentation]

> Man kann einen Einführungstext auch ganz gut verfassen, ohne zu
> beschreiben, dass Zeiger von und in Zahlen konvertiert werden können.
> Insofern würde ich sagen: wer mit der Repräsentation von Zeigern als
> Bitmuster anfängt, stellt das Thema von den Füßen auf den Kopf.


Wer eine im Grunde genommen einfache Sache moeglichst kompliziert und
verwirrend darstellen moechte, kann allerdings damit anfangen, allerlei
unwesentliche Details auf Leute abzuwerfen, denen sogar noch das
grundsaetzliche Verstaendnis der Konzepte fehlt. Klingt nach
Erstsemester "Ihr seid alle Idioten und von euch wollen wir moeglichst
viele loswerden" Mathematikvorlesung :-). Wird ggf auch mal abgeschafft,
wenn der Erfolg so durchschlagend war, das eine Mittelkuerzung droht.
Juergen Ilse (12.06.2019, 03:48)
Hallo,

Helmut Schellong <rip> wrote:
> On 06/11/2019 17:42, Stefan Reuther wrote:
> Interessant ist, daß auf fast allen Plattformen eine
> Konversion gar nicht stattfindet:
> Konversions-Algorithmus: ;
> Jede Adresse ist halt eine normale Integer-Zahl.
> Beispielsweise kann das Register eax nacheinander
> gemischt Integer mit Integer-Semantik und Adressen-Semantik
> enthalten, und nach Dereferenzierung zum Schluß eine Adresse
> unverändert an printf() übergeben.


Der Standard erlaubt auch Implementierungen, in denen es keinen int Typ
gibt, der gross genug ist um Pointer verlustfrei aufzunehmen. Es gab in
der Vergangenheit (und gibt moeglicherweise auch heute noch) Implementie-
rungen, bei denen das der Fall ist. In solchen Implementierungen gibt es
die Typen ptr_t und uptr_t dann nicht ...
Und der Standard wuerde auch Implementierungen erlauben, in denen sich
bei der konvertierung zwischen int Typen und pointern tatsaechlich das
Bitmuster aendern wuerde ...

Tschuess,
Helmut Schellong (12.06.2019, 13:24)
On 06/12/2019 03:48, Juergen Ilse wrote:
> Hallo,
> Helmut Schellong <rip> wrote:


> Der Standard erlaubt auch Implementierungen, in denen es keinen int Typ
> gibt, der gross genug ist um Pointer verlustfrei aufzunehmen. Es gab in
> der Vergangenheit (und gibt moeglicherweise auch heute noch) Implementie-
> rungen, bei denen das der Fall ist. In solchen Implementierungen gibt es
> die Typen ptr_t und uptr_t dann nicht ...
> Und der Standard wuerde auch Implementierungen erlauben, in denen sich
> bei der konvertierung zwischen int Typen und pointern tatsaechlich das
> Bitmuster aendern wuerde ...


Ich schrieb auch:
|Daß der C-Standard von einer Konversion schreibt, ist logisch.|
|Denn eine nicht-leere Konversion kann auch mal notwendig sein.|

Ich kenne das alles seit langer Zeit.
Nur in der Praxis habe ich noch nie auf Plattformen programmiert,
wo eine Adresse nicht so erscheint, wie von mir oben beschrieben.
Es scheint sie praktisch nicht zu geben.

intptr_t uintptr_t
Bonita Montero (30.06.2019, 13:47)
> Ich schrieb auch:
> |Daß der C-Standard von einer Konversion schreibt, ist logisch.|
> |Denn eine nicht-leere Konversion kann auch mal notwendig sein.|
> Ich kenne das alles seit langer Zeit.
> Nur in der Praxis habe ich noch nie auf Plattformen programmiert,
> wo eine Adresse nicht so erscheint, wie von mir oben beschrieben.
> Es scheint sie praktisch nicht zu geben.
> intptr_t   uintptr_t


Eben, Jürgen ist ein Spinner!
Es gibt ja in der IT viele Unwägbarkeiten zu beachten, aber es gibt
eben auch "Unwägbarkeiten" die keine sind da die nicht existieren.
Leute wie Jürgen können das eine nicht vom anderen unterscheiden
weil die ein gestörtes bzw. verschobenes Sicherheitsgefühl haben.
Ähnliche Themen