Dans certains cas il peut être commode d'avoir des tableaux indexés en
partant de 1, par exemple pour voir un tableau comme un arbre binaire
avec les fils de l'élément i aux index 2i et 2i + 1 plutôt que 2 * i + 1
et 2 * i + 2, et le parent à l'index i / 2 plutôt que (i + 1) / 2 - 1.
Est-il possible dans ce but d'utiliser un pointeur pointant *avant* le
début du tableau comme base pour faire les calculs ? Par exemple :
void heapsort(void *array, size_t nel, size_t width, compar_t *compar) {
char * const base1 = (char *) array - width;
/* la suite du code calculant à partir de base1
* mais ne déréférençant que base1 + 1 * width à base1 + nel * width
* et bien sûr jamais base1
*/
Je viens d'essayer de chercher dans la norme C99 [*] à ce sujet, et il
me semble que la réponse se trouve en 6.5.6, alinéa 8 :
> When an expression that has integer type is added to or subtracted
> from a pointer, [...] If both the pointer operand and the result point
> to elements of the same array object, or one past the last element of
> the array object, the evaluation shall not produce an overflow;
> otherwise, the behavior is undefined.
Donc j'ai l'impression que le code ci-dessus a un comportement indéfini.
Est-ce bien le cas, ou est-ce que j'interprète mal la norme ?
[*] J'utilise le document N1256 (C99 + TC3) : est-ce utile de le
préciser ou bien toutes les versions de C99 ont la même numérotation ?
--
Manuel Pégourié-Gonnard - http://people.math.jussieu.fr/~mpg/
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
espie
In article <jei37t$98j$, Manuel Pégourié-Gonnard wrote:
Bonjour,
Dans certains cas il peut être commode d'avoir des tableaux indexés en partant de 1, par exemple pour voir un tableau comme un arbre binaire avec les fils de l'élément i aux index 2i et 2i + 1 plutôt que 2 * i + 1 et 2 * i + 2, et le parent à l'index i / 2 plutôt que (i + 1) / 2 - 1.
Est-il possible dans ce but d'utiliser un pointeur pointant *avant* le début du tableau comme base pour faire les calculs ? Par exemple :
void heapsort(void *array, size_t nel, size_t width, compar_t *compar) { char * const base1 = (char *) array - width; /* la suite du code calculant à partir de base1 * mais ne déréférençant que base1 + 1 * width à base1 + nel * width * et bien sûr jamais base1 */
Je viens d'essayer de chercher dans la norme C99 [*] à ce sujet, et il me semble que la réponse se trouve en 6.5.6, alinéa 8 :
When an expression that has integer type is added to or subtracted from a pointer, [...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
Donc j'ai l'impression que le code ci-dessus a un comportement indéfini. Est-ce bien le cas, ou est-ce que j'interprète mal la norme ?
Oui, c'est bien ca.
Le seul cas de pointeur "invalide" que tu as le droit d'utiliser, c'est effectivement &(t[n]) pour un tableau de taille n (histoire de pouvoir refaire le classique for (i = 0; i != n; i++) avec les pointeurs).
-> si tu veux vraiment des tableaux indexes a 1 de facon portable, il va falloir perdre une case.
Si j'ai bonne memoire, le rationale associe a la norme specifie bien qu'il existe des implementations ou ecrire un *pointeur* invalide suffit a planter le programme... je n'en ai pas rencontre personnellement, mais je ne me m'amuserais pas a perdre la conformite pour une case...
In article <jei37t$98j$1@thue.elzevir.fr>,
Manuel Pégourié-Gonnard <mpg@elzevir.fr> wrote:
Bonjour,
Dans certains cas il peut être commode d'avoir des tableaux indexés en
partant de 1, par exemple pour voir un tableau comme un arbre binaire
avec les fils de l'élément i aux index 2i et 2i + 1 plutôt que 2 * i + 1
et 2 * i + 2, et le parent à l'index i / 2 plutôt que (i + 1) / 2 - 1.
Est-il possible dans ce but d'utiliser un pointeur pointant *avant* le
début du tableau comme base pour faire les calculs ? Par exemple :
void heapsort(void *array, size_t nel, size_t width, compar_t *compar) {
char * const base1 = (char *) array - width;
/* la suite du code calculant à partir de base1
* mais ne déréférençant que base1 + 1 * width à base1 + nel * width
* et bien sûr jamais base1
*/
Je viens d'essayer de chercher dans la norme C99 [*] à ce sujet, et il
me semble que la réponse se trouve en 6.5.6, alinéa 8 :
When an expression that has integer type is added to or subtracted
from a pointer, [...] If both the pointer operand and the result point
to elements of the same array object, or one past the last element of
the array object, the evaluation shall not produce an overflow;
otherwise, the behavior is undefined.
Donc j'ai l'impression que le code ci-dessus a un comportement indéfini.
Est-ce bien le cas, ou est-ce que j'interprète mal la norme ?
Oui, c'est bien ca.
Le seul cas de pointeur "invalide" que tu as le droit d'utiliser, c'est
effectivement &(t[n]) pour un tableau de taille n (histoire de pouvoir
refaire le classique for (i = 0; i != n; i++) avec les pointeurs).
-> si tu veux vraiment des tableaux indexes a 1 de facon portable, il va
falloir perdre une case.
Si j'ai bonne memoire, le rationale associe a la norme specifie bien qu'il
existe des implementations ou ecrire un *pointeur* invalide suffit a planter
le programme... je n'en ai pas rencontre personnellement, mais je ne me
m'amuserais pas a perdre la conformite pour une case...
In article <jei37t$98j$, Manuel Pégourié-Gonnard wrote:
Bonjour,
Dans certains cas il peut être commode d'avoir des tableaux indexés en partant de 1, par exemple pour voir un tableau comme un arbre binaire avec les fils de l'élément i aux index 2i et 2i + 1 plutôt que 2 * i + 1 et 2 * i + 2, et le parent à l'index i / 2 plutôt que (i + 1) / 2 - 1.
Est-il possible dans ce but d'utiliser un pointeur pointant *avant* le début du tableau comme base pour faire les calculs ? Par exemple :
void heapsort(void *array, size_t nel, size_t width, compar_t *compar) { char * const base1 = (char *) array - width; /* la suite du code calculant à partir de base1 * mais ne déréférençant que base1 + 1 * width à base1 + nel * width * et bien sûr jamais base1 */
Je viens d'essayer de chercher dans la norme C99 [*] à ce sujet, et il me semble que la réponse se trouve en 6.5.6, alinéa 8 :
When an expression that has integer type is added to or subtracted from a pointer, [...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
Donc j'ai l'impression que le code ci-dessus a un comportement indéfini. Est-ce bien le cas, ou est-ce que j'interprète mal la norme ?
Oui, c'est bien ca.
Le seul cas de pointeur "invalide" que tu as le droit d'utiliser, c'est effectivement &(t[n]) pour un tableau de taille n (histoire de pouvoir refaire le classique for (i = 0; i != n; i++) avec les pointeurs).
-> si tu veux vraiment des tableaux indexes a 1 de facon portable, il va falloir perdre une case.
Si j'ai bonne memoire, le rationale associe a la norme specifie bien qu'il existe des implementations ou ecrire un *pointeur* invalide suffit a planter le programme... je n'en ai pas rencontre personnellement, mais je ne me m'amuserais pas a perdre la conformite pour une case...
Jean-Marc Bourguet
(Marc Espie) writes:
Si j'ai bonne memoire, le rationale associe a la norme specifie bien qu'il existe des implementations ou ecrire un *pointeur* invalide suffit a planter le programme... je n'en ai pas rencontre personnellement, mais je ne me m'amuserais pas a perdre la conformite pour une case...
x86. Mais en mode segmenté, qui n'est plus utilisé à ma connaissance par personne (utiliser un segment par allocation était plus ou moins le modèle sous-jacent à la conception des segments, un des problèmes à l'utiliser maintenant serait le nombre de segments qui est ridiculement petit pour les normes actuelles, un autre le coût en perf; il y a d'autres architectures, mais je doute qu'il y ai beaucoup d'utilisateurs de C sur celles-là, ça tient du retro-computing même si la dernière fois que j'ai regardé, Unisys en vendait toujours un modèle).
A+
-- Jean-Marc FAQ de fclc: http://www.levenez.com/lang/c/faq Site de usenet-fr: http://www.usenet-fr.news.eu.org
espie@lain.home (Marc Espie) writes:
Si j'ai bonne memoire, le rationale associe a la norme specifie bien qu'il
existe des implementations ou ecrire un *pointeur* invalide suffit a planter
le programme... je n'en ai pas rencontre personnellement, mais je ne me
m'amuserais pas a perdre la conformite pour une case...
x86. Mais en mode segmenté, qui n'est plus utilisé à ma connaissance par
personne (utiliser un segment par allocation était plus ou moins le modèle
sous-jacent à la conception des segments, un des problèmes à l'utiliser
maintenant serait le nombre de segments qui est ridiculement petit pour les
normes actuelles, un autre le coût en perf; il y a d'autres architectures,
mais je doute qu'il y ai beaucoup d'utilisateurs de C sur celles-là, ça
tient du retro-computing même si la dernière fois que j'ai regardé, Unisys
en vendait toujours un modèle).
A+
--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Si j'ai bonne memoire, le rationale associe a la norme specifie bien qu'il existe des implementations ou ecrire un *pointeur* invalide suffit a planter le programme... je n'en ai pas rencontre personnellement, mais je ne me m'amuserais pas a perdre la conformite pour une case...
x86. Mais en mode segmenté, qui n'est plus utilisé à ma connaissance par personne (utiliser un segment par allocation était plus ou moins le modèle sous-jacent à la conception des segments, un des problèmes à l'utiliser maintenant serait le nombre de segments qui est ridiculement petit pour les normes actuelles, un autre le coût en perf; il y a d'autres architectures, mais je doute qu'il y ai beaucoup d'utilisateurs de C sur celles-là, ça tient du retro-computing même si la dernière fois que j'ai regardé, Unisys en vendait toujours un modèle).
A+
-- Jean-Marc FAQ de fclc: http://www.levenez.com/lang/c/faq Site de usenet-fr: http://www.usenet-fr.news.eu.org