Zugriffsverletzung beim Schreiben an Position...

Neonof

Mitglied
Hallo zusammen,

das letzte Mal hat das mit der Hilfe so gut geklappt, dass ich mich mit folgendem Problem nun wieder an die Community hier wende:

Die Aufgabe im Rahmen meines CS-Studiums ist die, mit Hilfe der Mandelbrot-Menge ein Fraktal zu erstellen und in eine Bitmap-Datei zu speichern. Die Funktion zum Speichern der Pixel in einer Bitmap-Datei ist bereits in einer header-Datei vorgegeben und an dieser Stelle nicht so wichtig. Auch ist die Rechenmethode hier nicht wichtig. Mein Problem liegt in Zeile 23. Beim Schreiben auf das dynamische Array picture tritt folgender Fehler auf: "Zugriffsverletzung beim Schreiben an Position...". Folglich muss versucht worden sein, außerhalb des Arrays zu schreiben. Durch Testen habe ich sichergestellt, dass dieser Zugriffsfehler bereits beim ersten Schleifendurchlauf auftritt, also mit a = 0 und b = 0. Geschrieben wird also direkt auf die Adresse, auf die picture zeigt. An dieser Stelle bin ich ratlos.

C++:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int given(int x, int y, int a, int b, int max_n, int n) {
	if (max_n == n || x*x + y*y > 4) return n;
	return given(x*x-y*y+a, 2*x*y+b, a, b, max_n, n+1);
}

int main() {
	system("cls");
	int hight, width, max_n;

	printf("\nBildma%ce (1920x1080): ", 225);
	scanf("%dx%d", &hight, &width);

	printf("\nMaximale Anzahl Iterationen: ");
	scanf("%d", &max_n);

	uint32_t *picture = (uint32_t)malloc(hight * width * 4);

	for (int a = 0; a < width; a++) {
		for (int b = 0; b < hight; b++) *(picture + b * width + a) = 0xFF00 - (max_n / given(0, 0, a, b, max_n, 1)) * 0xFF00;
	}

	printf("\n\nDas Bild wurde berechnet.");

	bmp_create("Mandelbrot.bmp", picture, width, hight);

	printf("\n\nDas Bild wurde erstellt.");

	Sleep(2000);
}

Ich danke wieder einmal im Vorraus schon für Hilfestellungen. :)
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
Hi

Dein Cast
C++:
uint32_t *picture = (uint32_t)malloc(hight * width * 4);
ist falsch und ich wundere mich, dass das so überhaupt durch den Compiler ging... Zudem: nimm height * width * sizeof(uint32_t). Semantisch das Gleiche, aber syntaktisch viel schöner.

Was liest du denn bei scanf() ein? Generell wäre es gut, würdest du alle Variablen initialisieren, also bei dir
C++:
int height = 1080; //"Höhe" auf Englisch ist übrigens "height", nicht "hight" :)
int width = 1920;
max_n = 0;
.
Des Weiteren: System-Calls sollten vermieden werden.

Also entweder war dein Problem, dass height und/oder width 0 waren oder das ist nicht dein aktueller Code.
/EDIT: Nee, kann eigentlich auch nicht sein... -> Wohl am ehesten entweder picture == NULL oder nicht aktueller Code.

Gruss
cwriter

/EDIT: Hehe... Hast du geprüft, ob picture==NULL ist? Und btw: Bei dir fehlt ein free()...
 
Zuletzt bearbeitet:

Neonof

Mitglied
Ich habe die Schönheitskorrekturen gemacht und zum Verständnis die scanf-Befehle einmal rausgenommen. picture ist geprüft und definitiv nicht null. Wenn also malloc offensichtlich etwas zurückgibt, muss doch die Speicherreservierung korrekt funktioniert haben. Wie wäre der Aufruf denn korrekter?

Hier der jetzige Code. Zuvor war er etwas abgehändert, um unnötigen kram nicht drinne zu haben, da da auch eine andere Aufgabe bearbeitet wurde. Nun noch einmal wortwörtlich in einer eigenen Datei:

C++:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "C:\Users\Neonof\Documents\Studium\2016 Computer Science\7 1. Semester\4 Prozedurale Programmierung\06 Skalarprodukt\sheet06\libBMP.h"

int given(int x, int y, int a, int b, int max_n, int n) {
	printf("\n\t\tn: %d\t%d", n, x*x + y*y);
	if (max_n == n || x*x + y*y > 4) return n;
	return given(x*x - y*y + a, 2 * x*y + b, a, b, max_n, n + 1);
}

int main() {
	int wahl;
	int height = 200, width = 200, max_n = 50;

	/*
	printf("\nBildma%ce (1920x1080): ", 225);
	scanf("%dx%d", &height, &width);

	printf("\nMaximale Anzahl Iterationen: ");
	scanf("%d", &max_n);
	*/

	uint32_t *picture = (uint32_t)malloc(height * width * sizeof(uint32_t));
	printf("%d", picture);

	for (int a = 0; a < width; a++) {
		for (int b = 0; b < height; b++) {
			*(picture + b * width + a) = 0xFF00 - (max_n / given(0, 0, a, b, max_n, 1)) * 0xFF00;
			printf("\n\t3");
		}
	}

	printf("\n\nDas Bild wurde berechnet.");

	bmp_create("Mandelbrot.bmp", picture, width, height);

	free(picture);

	printf("\n\nDas Bild wurde erstellt.");

	Sleep(2000);
}

selbiger Fehler
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
Du castest auch noch immer auf uint32_t...
Da du unter Windows zu arbeiten scheinst: Hast du ein x64-System und den Compiler auf 64bit gestellt? Dann ist gut möglich, dass das der Fehler ist. Beim Cast auf uint32_t (4Bytes) verlierst du die höheren 4 Bytes, falls sizeof(void*) == 8 ist. Und das ist auf 64bit-Systemen mit 64bit-Programmen halt mal der Fall...

Dein printf("%d", picture); wäre dann auch nicht die ganze Wahrheit, denn auch da fehlt ein Teil des void*.


picture ist geprüft und definitiv nicht null.
Mit Prüfen meint man eigentlich:
C++:
if(picture == NULL)
{
    perror("Allocation failed");
    return -1;
}
oder so...

Wenn also malloc offensichtlich etwas zurückgibt, muss es doch korrekt funktioniert haben, oder nicht?
malloc kann NULL zurückgeben. Dann hat es nicht funktioniert. Aber falls malloc() einen Wert ungleich Null zurückgibt, hat es funktioniert. Wenn es aber einen 64-Bit-Wert zurückgibt und du den beschneidest, dann haben wir ein schönes Undefined Behaviour.

#define _CRT_SECURE_NO_DEPRECATE
Also wenn du schon VS nutzt: Was sagt denn der Debugger? (Kleiner Tipp: Der automatische Abbruch kann dir die Variablen durcheinanderwirbeln. Du musst mit Haltepunkten arbeiten, um die Werte zu prüfen. Zudem darfst du nicht im Releasemode sein.)

Allerdings heisst das auch, dass du höchstwahrscheinlich nicht mit x64 unterwegs bist, ausser, du hast diese Einstellung umgestellt: Default in VS ist x86...

Nun noch einmal wortwörtlich in einer eigenen Datei:
Wenn es den Fehler tatsächlich noch gibt: Was sagt denn die Fehlermeldung? Vor allem: An welcher Adresse besteht die Verletzung?
Und was sagt
C++:
printf("%p", picture);
?

Gruss
cwriter
 

Neonof

Mitglied
Du castest auch noch immer auf uint32_t...
Das habe ich deshalb getan, weil der Pointer auf das Array an die Funktion bmp_create übergeben wird, die in der header-Datei mit uint32_t arbeitet. Ich wollte sie dort erst ungern umändern, weil das File auch für andere Aufgaben verwendet wurde. Ich habe nun eine eigene Datei dafür gemacht. Eigentlich sollte es aber gehen, da der Typ und die selbe Methode der Speicherallokation auch bei der Verwendung in vorherigen Aufgaben kein Problem darstellte.

Dein printf("%d", picture); wäre dann auch nicht die ganze Wahrheit, denn auch da fehlt ein Teil des void*.
Eigentlich wollte ich ja auch nicht sehen, auf welchen Wert der Pointer zeigt, sondern wie die Adresse lautet. Da der Compiler dabei aber auch meckert, gebe ich mich bei dem Vorhaben geschlagen...

Das System ist ein x64-System und der Compiler ist ebenfalls auf 64bit gestellt. Allerdings hatte ich tatsächlich den release-mode aktiviert.

Wenn es aber einen 64-Bit-Wert zurückgibt und du den beschneidest, dann haben wir ein schönes Undefined Behaviour.
Tatsächlich gab es dazu eine Warnung:

Screenshot: Variablenbelegung + Fehlerliste

Hier sieht man auch schön, dass die Adresse, auf die der Pointer zeigt, nicht gelesen werden kann.

Wenn es den Fehler tatsächlich noch gibt: Was sagt denn die Fehlermeldung? Vor allem: An welcher Adresse besteht die Verletzung?

Screenshot: Fehlermeldung

Alles was uint32_t war, ist jetzt also int. Dennoch steht dort weiterhin '"Typumwandlung": Zeigerverkürzung von "void *" zu "int"'. void * meint doch, dass der Zeiger, den malloc zurückgibt, typenlos ist.

Das (uint32_t) bzw. jetzt (int) vor malloc sollte doch für die korrekte Interpretation sorgen. Wenn ich richtig verstanden habe, gibt malloc auf x64-Systemen längere als 4 Byte lange Zeiger zurück, für die entsprechend große Variablen verwendet werden müssen. Nächst höheres wäre 8 Byte. Mir war für c kein Datentyp bekannt, der größer ist.

später:
Versuchs- (und naheliegender) -weise habe ich aus uint32_t nun einmal uint64_t gemacht. Tatsächlich geht es nun schon etwas weiter. Die ersten Durchläufe funktionieren. Irgendwann als b dann 107 erreicht, bricht das Programm mit dem gleichen Problem wieder ab. Diesmal ist die Adresse eine etwas andere:

Screenshot: Fehlermeldung

Auch in der Fehlerliste steht nun kein Eintrag mehr.
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
Das habe ich deshalb getan, weil der Pointer auf das Array an die Funktion bmp_create übergeben wird, die in der header-Datei mit uint32_t arbeitet. Ich wollte sie dort erst ungern umändern, weil das File auch für andere Aufgaben verwendet wurde. Ich habe nun eine eigene Datei dafür gemacht. Eigentlich sollte es aber gehen, da der Typ und die selbe Methode der Speicherallokation auch bei der Verwendung in vorherigen Aufgaben kein Problem darstellte.
Das ist ja der Witz von UB. Manchmal geht's, manchmal nicht. Das macht es gefährlich. "Geht ja" != korrekt.
Mal abgesehen davon bringt das gar nix. Der Weg ist folgender:

malloc() gibt void* zurück.
Du castest auf (uint32_t), also wird dieses void* zu uint32_t umgewandelt.
Der Zieltyp ist aber uint32_t*, daher wird uint32_t auf uint32_t* gewandelt (implizit).

Du hast immer noch uint32_t* als picture, der Cast ändert daran gar nix (ausser einem langsameren und weniger portablem Programm).

Eigentlich wollte ich ja auch nicht sehen, auf welchen Wert der Pointer zeigt, sondern wie die Adresse lautet. Da der Compiler dabei aber auch meckert, gebe ich mich bei dem Vorhaben geschlagen...
Nein...
C++:
printf("%d", *picture); //Korrekt
printf("%d", picture); //Inkorrekt, %d erwartet 4 Bytes, der parameter ist (möglicherweise) 8 Byte gross.
printf("%p", picture); //Korrekt: %p designiert einen Pointer, picture ist ein Pointer
printf("%p", *picture); //Inkorrekt: %p erwartet auf deinem System 8 Bytes, du gibst nur 4 als Parameter.

Hier sieht man auch schön, dass die Adresse, auf die der Pointer zeigt, nicht gelesen werden kann.
Wo? Im Auto-Fenster? Im Release-Mode geht das nicht. Im Debug-Mode geht es nicht, weil der Pointer, den du verunstaltet und übelst misshandelt hast, völlig verkrüppelt ist und keiner Funktion mehr nachkommen kann.

Alles was uint32_t war, ist jetzt also int. Dennoch steht dort weiterhin '"Typumwandlung": Zeigerverkürzung von "void *" zu "int"'. void * meint doch, dass der Zeiger, den malloc zurückgibt, typenlos ist.
Eieiei. void != void*.
Ein void ist ein nichts (Englisch "void" = Leere, Nichts). Ein void* ist ein Pointer und in C, aber nicht C++ äquivalent zu int*, char*, FILE*, bla*, und auch int**, int***, int*****, etc.
void* wird nur deshalb bei malloc und Co. verwendet, weil es sich immer casten lässt. Es ist quasi Typenlos, und du musst einen Typ geben.
Dem OS ist es egal, wofür du den Speicher brauchst, aber dir nicht. Theoretisch könntest du aber sowas hier machen:
C++:
void* test = malloc(sizeof(int)); //test ist void*
((char*)test)[0] = 'a';
((char*)test)[1] = 'b';
((char*)test)[2] = 'c';
((char*)test)[3] = '\0';

//Was ist test jetzt?
//Antwort: Syntaktisch (was der Compiler sieht): void*. Unbrauchbar.
//Aber ich könnte das hier machen:
printf("%s", (char*)test);
//Ausgabe: abc

//Semantisch also ein String. Aber ich könnte auch auf int* casten und die Zahl auslesen. void* ist alles und nichts zugleich.
free(test);

Sobald ein Typ ein oder mehrere '*' dahinterstehen hat, ist er gleich gross wie jeder andere Typ mit einem (oder mehr) Asterisk(en). Das ist ein bisschen verwirrend, aber im Prinzip kannst du dir es so vorstellen: Das letzte Asterisk zählt. Alles, was links davon steht, sind die Typen, die man erhält, wenn man dereferenziert, also ein Asterisk VOR die VARIABLE setzt. Ein Beispiel:
C++:
int*** i;
//typeof i: void* == (int**)* == ((int*)*)*
//typeof *i == int**
//typeof **i == int*
//typeof ***i == int
Auch hier: Du kannst auf jeder Stufe irgendeinen Typ casten. Völlig wurst. Du musst nur aufpassen, dass du im richtigen Speicherbereich bleibst.

Bei dir ist jetzt, wie schon gefühlte hundert Mal gebetsmühlenartig wiederholt, der Pointer doppelt so gross wie ein int, also sizeof(int*) = 2 * sizeof(int) = sizeof(void*).

Screenshot: Fehlermeldung
Seufz. Die ist nutzlos alleine. Du müsstest mir schon sagen, was das printf("%p") vorher ausgegeben hat (Fehlermeldung und printf aus demselben Durchlauf)... Dort sähe man: Beim einen Wert ist die eine Hälfte anders.

Das (uint32_t) bzw. jetzt (int) vor malloc sollte doch für die korrekte Interpretation sorgen. Wenn ich richtig verstanden habe, gibt malloc auf x64-Systemen längere als 4 Byte lange Zeiger zurück, für die entsprechend große Variablen verwendet werden müssen. Nächst höheres wäre 8 Byte. Mir war für c kein Datentyp bekannt, der größer ist.
Wat?
malloc() gibt immer einen Zeiger zurück. Fertig. Es gibt pro System nur EINE EINZIGE Zeigergrösse, alles andere ist Quatsch.
Und 8 Bytes ist nicht die "nächsthöhere" Grösse; es ist durchaus möglich, ein System mit 5 Byte grossen Zeigern zu bauen. Dass das nicht viel Sinn macht, ist ein anderes Problem.
Nun ist der Zeiger auf 64bit Systemen nicht einfach 8 Byte gross. Du hast Windows, Windows hat alle Bibliotheken doppelt. Rate mal, warum.
Wenn Pointer immer 8 Byte gross wären, kämen alte 32-Bit Programme in Teufels Küche, sie wären nicht mehr Binärkompatibel und liefen meist gar nicht mehr. Daher: Wenn du deinen Compiler auf 32bit (x86) umstellst, wirst du 4 Byte grosse Pointer haben. Auf einem 64bit-System. Cool, oder?
Zusammenfassend: Der Compiler und das OS bestimmen die (nutzbaren) Pointergrössen, man kann auf der CPU mit PAE und memory mapping auch 32-bit-Programme auf höhere Adressen mappen, aber das ist ein anderes Thema.

Also hör gefälligst auf, irgendwas in der Gegend herum zu casten. Es ist nicht nur falsch, sondern kreuzfalsch. Zudem: Warnungen sind als Errors zu lesen. Wenn du eine Warnung hast, hast du etwas falsch gemacht. Punkt.

Versuchs- (und naheliegender) -weise habe ich aus uint32_t nun einmal uint64_t gemacht. Tatsächlich geht es nun schon etwas weiter. Die ersten Durchläufe funktionieren. Irgendwann als b dann 107 erreicht, bricht das Programm mit dem gleichen Problem wieder ab. Diesmal ist die Adresse eine etwas andere:

Screenshot: Fehlermeldung

Auch in der Fehlerliste steht nun kein Eintrag mehr.
Nö, keine Lust mehr, weiterzuraten. Du kannst doch nicht einfach irgendwelche Typen nehmen, um zu casten!? Hier geht es sogar mit uint64_t, aber es ist syntaktisch kreuzfalsch. Lies meine Beiträge und verstehe sie doch bitte.

Gruss
cwriter
 
Zuletzt bearbeitet:

Neonof

Mitglied
Autsch... ich verstehe schon, weshalb du keine Lust mehr hast. Vielen Dank für die Mühe.
Boar bin ich blöd.. Den Fehler habe ich jetzt gefunden. Der jetzige Code sieht so aus:

C++:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "C:\Users\Neonof\Documents\Studium\2016 Computer Science\7 1. Semester\4 Prozedurale Programmierung\06 Skalarprodukt\sheet06\libBMP.h"

int given(int x, int y, int a, int b, int max_n, int n) {
	printf("\n\t\tn: %d\t%d", n, x*x + y*y);
	if (max_n == n || x*x + y*y > 4) return n;
	return given(x*x - y*y + a, 2 * x*y + b, a, b, max_n, n + 1);
}

int main() {
	int height = 200, width = 200, max_n = 50;
	

	printf("\nBildma%ce (1920x1080): ", 225);
	scanf("%dx%d", &height, &width);

	printf("\nMaximale Anzahl Iterationen: ");
	scanf("%d", &max_n);

	uint32_t *picture = (uint32_t*)malloc(height * width * sizeof(uint32_t));
	printf("%p", picture);

	for (int a = 0; a < width; a++) {
		for (int b = 0; b < height; b++) {
			*(picture + b * width + a) = 0xFF00 - (max_n / given(0, 0, a, b, max_n, 1)) * 0xFF00;
			printf("\n\t3");
		}
	}

	printf("\n\nDas Bild wurde berechnet.");

	bmp_create("Mandelbrot.bmp", picture, width, height);

	free(picture);

	printf("\n\nDas Bild wurde erstellt.");

	Sleep(2000);
}

Ich habe den Aufruf von malloc ewig verglichen und jedes mal übersehen, dass natürlich noch das '*' dahinter gehört. Auch bei der Überlegung wie ich verhindern kann, dass Teile der Adresse verloren gehen, habe ich einfach drum herum gedacht, statt daran zu denken, dass ich einfach nicht den Typen Pointer genommen habe.

Die Tatsache zur Kompatibilität, dass Pointer auf x64 und x86 Systemen unterschiedliche Größen aufweisen, war mir neu. Dann hätte ich das eigentliche Problem eigentlich schon umgehen können, indem ich den Modus auf x86 gestellt hätte, der die ganze Zeit auf x64 stand... *Schande über mich
Natürlich wäre es dann syntaktisch immernoch verkehrt gewesen. Ich habe nun wieder alles auf 32bit geändert und lasse das Programm auch für x86 kompilieren.

Vielen Dank für die Erklärungen und vor Allem die Geduld. Damit ist mein Problem gelöst und das Verständnis dafür da.
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
Dann hätte ich das eigentliche Problem eigentlich schon umgehen können, indem ich den Modus auf x86 gestellt hätte, der die ganze Zeit auf x64 stand...
Jain. Das Asterisk wäre dennoch nötig gewesen: Das Programm wäre zwar durchgelaufen, aber korrekt wäre der Code nicht gewesen: C soll ja gerade plattformunabhängig sein. Naja. Mehr oder weniger. Aber prinzipiell sollte sich jeder C-Code auf x86 und x64 konpilieren lassen.
Mit dem Asterisk beim Cast stimmt dieser jetzt und das Programm sollte auf 32 und 64bit (und 128bit in ferner Zukunft :) ) laufen.
Daher hast du Recht mit
Natürlich wäre es dann syntaktisch immernoch verkehrt gewesen.

Aber sofern dein Professor eine korrekte Implementierung von seinen vorgebenen Funktionen abgeliefert hat, läuft dein Code jetzt auch auf x64. Der Compiler ändert die Pointergrössen automatisch, wenn du die Casts auch als Pointer definiert hast.

Vielen Dank für die Erklärungen und vor Allem die Geduld.
Naja. Letztere war jetzt nicht so prall. Freut mich, dass du dennoch die Lösung gefunden hast :)

Gruss
cwriter
 

sheel

I love Asm
Hi

Ein paar generelle Sachen fürs weitere Programmieren:

Beim Schreiben auf das dynamische Array picture tritt folgender Fehler auf: "Zugriffsverletzung beim Schreiben an Position...". Folglich muss versucht worden sein, außerhalb des Arrays zu schreiben.
Möglich, aber nicht unbedingt. Das Array muss nicht unbedingt zu klein sein, und der Fehler muss nicht einmal in der Zeile liegen.
Wie das letzte Mal beschrieben ist eine mögliche Auswirkung von UB, dass sich beliebige Variablenwerte grundlos ändern können. Ein Fehler in einer anderen Zeile könnte den Arraypointer mit Müll überschreiben.
Oder das Problem kann durch den Compiler und/oder Prozessor entstehen, der Anweisungen auch in anderer Reihenfolge anordnen darf (und tut), solange bei UB-freiem Code das selbe Ergebnis rauskommt. Ein Fehler in einer Zeile kann deshalb auch Probleme vor oder nach dieser Zeile auslösen (deshalb, und auch aus vielen anderen Gründen).
...kurz, UB ist nicht nur Undefined Behaviour, sondern auch UnBerechenbar. Komische Fehler können passieren, auch wenn es noch so wenig Sinn macht.

Ob scanf erfolgreich war sollte auch geprüft werden. Der Rückgabewert ist die Anzahl der erfolgreich eingelesenen Variablen.

Die "Schönheitskorrektur", den Variablen vor Verwendung einen Wert zu geben (den sie bei fehlgeschlagenen scanf sonst nicht haben), ist eigentlich Pflicht. Nicht machen = UB (wieder mal).

"Warnungen" in C sind durchschnittlich schlimmer als Fehler. Ja wirklich. Ein Fehler zB. ist ein vergessenes Semikolon, eine Warnung ist zB. UB.

Das habe ich deshalb getan, weil der Pointer auf das Array an die Funktion bmp_create
Wenn diese Funktion so vorgegeben ist hat dein Lehrer etwas falsch gemacht.

Eigentlich sollte es aber gehen, da der Typ und die selbe Methode der Speicherallokation auch bei der Verwendung in vorherigen Aufgaben kein Problem darstellte.
UB. Wieder. Wie cwriter sagt, manchmal gehts auch. Aber nur manchmal.

Mir war für c kein Datentyp bekannt, der größer ist.
Das wird dich sehr überraschen, aber: Wie groß ints in C sind, oder was ints sonst noch sind, ist nirgends festgelegt.

Es gibt ein paar Kriterien, das wichtigste davon ist "welche Zahlenwerte kann die (int-)Variable mindestens speichern". Solange das erfüllt ist ist alles andere egal. Ein int kann größer sein und daher größere Zahlen speichern können, es kann aber auch größer sein ohne die zusätzlichen Bit für den Wert zu verwenden. Es kann das Bitmuster 0000...0000 als Zahlenwert 0 verstehen oder auch als 1234. Andere Bitmuster können das Aufhängen vom Prozessor bewirken. Welche Bitmuster negative Zahlen haben ist sowieso ganz offen. Es gibt Endianess. Es gibt Alignment. Es gibt evt. spezielle Speicherbereiche, die nur ints (aber keine Pointer) speichern können, weil sich der Computer sonst auch aufhängt. usw.usw.
... C ist in den Angelegenheiten nicht die einfachste Sprache.

Für Pointer gelten diese ganzen Möglichkeiten auch, allerdings können Pointer in allen Punkten anders sein als ints. Niemand verlangt, dass die Werte von ints und Pointern im RAM irgendwie kompatibel sind.
Deswegen, ganz unabhängig von der Größe der Variable, castet man Pointer einfach nicht in ints (Punkt aus). Vergiss am besten ganz, dass eine Adresse eine Zahl ist (bzw. sein kann), es muss nämlich keine Zahl sein. Eine Adresse ist eine Adresse, sonst nichts.

...
Ja, C kann kompliziert werden :D

edit:
Natürlich müssen diese ganzen Probleme nicht existieren, es gibt genug Computer bei denen ein Pointer wirklich wie ein int ist (nur evt. die Größe anders, oder nicht einmal das). Aber auch in diesen Fällen darf sich der Compiler darauf verlassen, dass man keinen UB-Code schreibt, und bei UB einfach falsche/unpassende Prozessoranweisungen ins Programm schreiben. Der Compiler macht das auch nicht aus Bösartigkeit oder so, sondern die ganzen Codeumordnungen usw. sind zB. um die Geschwindigkeit vom Programm zu erhöhen.
 
Zuletzt bearbeitet:

Neonof

Mitglied
Haha, vielen Dank. :D

Dazu eine Frage:
Wenn der Prozessor den Code umstrukturiert, ist diese Umstrukturierung dann immer gleich oder kann die jedes mal anders sein? Sprich tritt einmal ein Fehler auf und ich will scanf testen, dann funktioniert es und eigentlich kann der Fehler aber doch da liegen und es war nur Zufall?