Euh désolé, mais j'ai franchement l'impression que tu essayes de généraliser à partir d'un cas complètement exotique, mais bon j'ai un peu eu du mal à suivre quand même c'est pourquoi je vais tenter d'être clair (sans être sûr que je le serais plus que toi :-)...
Cette histoire de prépocesseur qui remplace les 0 par des pointeurs invalides si le 0 n'est pas suffisament invalide m'a l'air complétement tordue!!!
C'est peut être le cas sur certaines architectures où on veut à tout pris pouvoir exploiter l'adresse 0 au mépris de la portabilité (je n'ai aucune expérience de ces machines et c'est la première fois que j'en entend parler), mais en règle générale, en C, l'adresse 0 est considérée comme une adresse invalide. Point barre. C'est une convention indépendante du fait que le hardware accepte les lectures ou écriture à l'adresse 0 (par 0 j'entend « (void*) 0 » bien sûr) .
Quand tu as une fonction qui retourne un pointeur 0 (ou NULL), ou une une variable pointeur contenant 0, on considère que ce pointeur est vide et ne pointe nulle part, et qu'il ne faut surtout pas lire ou écrire l'adresse pointée.
Si tu as : char *p = NULL; //(ou 0)
et que tu fais un : « if (*p) {...} » ou « *p='x' ; »
le compilateur ne fera pas d'erreur (on va voir pourquoi) mais c'est pourtant incorrect!
Maintenant il se peut que tu fasses de la programmation bas niveau et que tu aies besoin d'écrire à l'adresse 0 (tu veux par exemple fixer un vecteur d'interruption), tu as tout à fait le droit de faire un :
#define RESET_VECTOR (void*) 0
puis un : RESET_VECTOR = mon_gestionnaire_de_reset;
Il faut cependant remarquer qu'il s'agit alors d'une constante... et c'est effectivement pour ça que le compilateur te laisse accéder à 0 comme tu le veux et que cette convention du « 0 <=> adresse invalide » n'est pas connu du compilateur.
Si tu as un système où l'adresse 0 est de la RAM comme à l'adresse 0x123456 (par ex), il sera malheureusement impossible de l'exploiter normalement, comme par exemple si l'adresse était renvoyée par un malloc(), car si cette fonction te renvoie 0, ça ne signifie pas que tu as un bloc alloué à l'adresse 0, mais qu'il n'a pas été possible de faire l'allocation, car la convention « 0 <=> invalide » est par contre intégrée dans toute bibliothèque un minimum standard. Rien ne t'empêche cependant de réécrire un malloc() qui renvoie 0xFFFFFFFF si l'allocation ne peut pas se faire pour pouvoir exploiter normalement ton système, mais je t'avouerais que je préfèrerais perdre 1 octet de RAM plutôt que tenter de réinventer un ersatz de langage C avec des conventions différentes.
Ça a d'ailleurs été un problème important rencontré par Dave Small (pour les ex-lecteurs de STMAG...) lorsqu'il a codé son émulateur Mac sur ST, car le Mac autorisait la lecture de l'adresse 0, alors que le ST déclanchait une erreur de bus. Beaucoup de programmeurs sous MAC n'hésitaient pas écrire du code tel que ça :
if ( *p == TRUCMUCHE && p ) {...}
qui marchait sur un MAC mais plantait sur un ST (il fallait bien sûr inverser les 2 tests pour que cela soit correct), et il a donc dû bidouiller comme un fou pour récupérer l'erreur de bus et continuer le programme comme si de rien n'était, ce qui était théoriquement impossible, et qui lui a donc vallu beaucoup de mérite de tous les petits programmeurs en herbe comme moi (et sans d'autre porgrammeurs plus expérimenté aussi!)
[^] # Re: Petites precisions
Posté par calandoa . En réponse au journal J'adore Linus. Évalué à 5.
Cette histoire de prépocesseur qui remplace les 0 par des pointeurs invalides si le 0 n'est pas suffisament invalide m'a l'air complétement tordue!!!
C'est peut être le cas sur certaines architectures où on veut à tout pris pouvoir exploiter l'adresse 0 au mépris de la portabilité (je n'ai aucune expérience de ces machines et c'est la première fois que j'en entend parler), mais en règle générale, en C, l'adresse 0 est considérée comme une adresse invalide. Point barre. C'est une convention indépendante du fait que le hardware accepte les lectures ou écriture à l'adresse 0 (par 0 j'entend « (void*) 0 » bien sûr) .
Quand tu as une fonction qui retourne un pointeur 0 (ou NULL), ou une une variable pointeur contenant 0, on considère que ce pointeur est vide et ne pointe nulle part, et qu'il ne faut surtout pas lire ou écrire l'adresse pointée.
Si tu as : char *p = NULL; //(ou 0)
et que tu fais un : « if (*p) {...} » ou « *p='x' ; »
le compilateur ne fera pas d'erreur (on va voir pourquoi) mais c'est pourtant incorrect!
Maintenant il se peut que tu fasses de la programmation bas niveau et que tu aies besoin d'écrire à l'adresse 0 (tu veux par exemple fixer un vecteur d'interruption), tu as tout à fait le droit de faire un :
#define RESET_VECTOR (void*) 0
puis un : RESET_VECTOR = mon_gestionnaire_de_reset;
Il faut cependant remarquer qu'il s'agit alors d'une constante... et c'est effectivement pour ça que le compilateur te laisse accéder à 0 comme tu le veux et que cette convention du « 0 <=> adresse invalide » n'est pas connu du compilateur.
Si tu as un système où l'adresse 0 est de la RAM comme à l'adresse 0x123456 (par ex), il sera malheureusement impossible de l'exploiter normalement, comme par exemple si l'adresse était renvoyée par un malloc(), car si cette fonction te renvoie 0, ça ne signifie pas que tu as un bloc alloué à l'adresse 0, mais qu'il n'a pas été possible de faire l'allocation, car la convention « 0 <=> invalide » est par contre intégrée dans toute bibliothèque un minimum standard. Rien ne t'empêche cependant de réécrire un malloc() qui renvoie 0xFFFFFFFF si l'allocation ne peut pas se faire pour pouvoir exploiter normalement ton système, mais je t'avouerais que je préfèrerais perdre 1 octet de RAM plutôt que tenter de réinventer un ersatz de langage C avec des conventions différentes.
Ça a d'ailleurs été un problème important rencontré par Dave Small (pour les ex-lecteurs de STMAG...) lorsqu'il a codé son émulateur Mac sur ST, car le Mac autorisait la lecture de l'adresse 0, alors que le ST déclanchait une erreur de bus. Beaucoup de programmeurs sous MAC n'hésitaient pas écrire du code tel que ça :
if ( *p == TRUCMUCHE && p ) {...}
qui marchait sur un MAC mais plantait sur un ST (il fallait bien sûr inverser les 2 tests pour que cela soit correct), et il a donc dû bidouiller comme un fou pour récupérer l'erreur de bus et continuer le programme comme si de rien n'était, ce qui était théoriquement impossible, et qui lui a donc vallu beaucoup de mérite de tous les petits programmeurs en herbe comme moi (et sans d'autre porgrammeurs plus expérimenté aussi!)