Partage
  • Partager sur Facebook
  • Partager sur Twitter

La LibC des Zéros

Objectif : recoder la libC.

2 août 2012 à 15:03:57

Citation : Holt

Je suis pas contre les goto, mais si tu utilises un const char **, il faut faire un double dé-référencement et une post incrémentation sur la valeur simplement dé-référencé (oula ma phrase veut dire quelque chose ? :p ) dans le switch... :(



De toute manière, avec un for c'est pareil (mis à part qu'il y a une centralisation de l'incrémentation dans la structure de contrôle en elle-même). Au pire, tu peux utiliser un tampon d'une seule indirection pour éviter les déférencements excessifs.
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
2 août 2012 à 15:07:51

Citation : Lucas-84

Citation : Holt

Je suis pas contre les goto, mais si tu utilises un const char **, il faut faire un double dé-référencement et une post incrémentation sur la valeur simplement dé-référencé (oula ma phrase veut dire quelque chose ? :p ) dans le switch... :(



Non, mais tu peux faire le switch et l'incrémentation de manière séparée si ça gêne la lisibilité.

/* incrémentation */

switch (**s) {
    /* ... */
}



De toute manière, avec un for c'est pareil (mis à part qu'il y a une centralisation de l'incrémentation dans la structure de contrôle en elle-même). Au pire, tu peux utiliser un tampon d'une seule indirection pour éviter les déférencements excessifs.


Oui mais dans ce cas, je perds un peu l'utilité du goto je trouve :) Je m'en servirais certainement dans d'autres cas, pour l'instant je reste avec mon code actuel :)
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 15:13:58

Citation : Holt

Citation : Lucas-84

Citation : Holt

Je suis pas contre les goto, mais si tu utilises un const char **, il faut faire un double dé-référencement et une post incrémentation sur la valeur simplement dé-référencé (oula ma phrase veut dire quelque chose ? :p ) dans le switch... :(



Non, mais tu peux faire le switch et l'incrémentation de manière séparée si ça gêne la lisibilité.

/* incrémentation */

switch (**s) {
    /* ... */
}



De toute manière, avec un for c'est pareil (mis à part qu'il y a une centralisation de l'incrémentation dans la structure de contrôle en elle-même). Au pire, tu peux utiliser un tampon d'une seule indirection pour éviter les déférencements excessifs.


Oui mais dans ce cas, je perds un peu l'utilité du goto je trouve :) Je m'en servirais certainement dans d'autres cas, pour l'instant je reste avec mon code actuel :)



Ok. Juste pour terminer sur ce sujet, un code d'exemple.

#include <stdio.h>

enum flag_t {
	FLAG_LJUST = 1 << 0,
	FLAG_PSIGN = 1 << 1,
	FLAG_SPACE = 1 << 2,
	FLAG_AFORM = 1 << 3,
	FLAG_ZEROS = 1 << 4
};

static enum flag_t get_flags(const char **s)
{
	enum flag_t flag = 0;
 start:
	switch (*++*s) {
	    case '-': flag |= FLAG_LJUST; goto start;
	    case '+': flag |= FLAG_PSIGN; goto start;
	    case ' ': flag |= FLAG_SPACE; goto start;
	    case '#': flag |= FLAG_AFORM; goto start;
	    case '0': flag |= FLAG_ZEROS; goto start;
	}
	return flag;
}

int main(void)
{
	char const *s = "%#-d";
	enum flag_t f = get_flags(&s);
	printf("%d - %s\n", f, s);
	return 0;
}
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
2 août 2012 à 15:26:09

Le nombre d'étoiles dans un code n'augmente pas son skill hein ^^ c'est quoi cette manie de mettre des doubles pointeur partout?
(on en parlait hier justement)
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 15:28:24

Citation : Mr21

Le nombre d'étoiles dans un code n'augmente pas son skill hein ^^ c'est quoi cette manie de mettre des doubles pointeur partout?



Avec une indirection, résultat :

9 - %#-d


Avec deux indirections, résultat :

9 - d


Et c'est le deuxième résultat qui est attendu. ;)
  • Partager sur Facebook
  • Partager sur Twitter
Staff désormais retraité.
2 août 2012 à 15:33:27

Citation : Holt

En ce qui concerne les formats flottants, ils sont assez proche de la représentation du printf standard chez moi, à 1-3 digits près (je me pencherais là dessus, je pense que l'implémentation de mingw fait une approximation avant de rajouter des 0, ce que je ne fais pas... ). Le format %g n'est pas "correct", il va simplement choisir entre e et f en fonction de la valeur... Je n'ai pas eu le temps de regarder sur internet les spécifications précises (s'il y en a) de ce format.



Tu as essayé avec de très grands nombre comme FLT_MAX ? Parce que chez moi, c'est loin d'être juste à 3 chiffres prêts :p

#include <float.h>
#include <math.h>
#include <stdio.h>
#include <string.h>


void
print_double(double n)
{
	static char buf[64];
	double ipart = floor(n);
	double fpart = n - ipart;
	unsigned i;

	for (i = 0; ipart > 0.; ++i, ipart = floor(ipart / 10.))
		buf[i] = "0123456789"[(int)fmod(ipart, 10)];
	buf[i] = '\0';

	size_t len = strlen(buf);

	while (len-- != 0)
		putchar(buf[len]);
	putchar('\n');
}


int
main(void)
{
	double n = FLT_MAX;

	print_double(n);
	printf("%f\n", n);
	return 0;
}


Résultat :

340282346638528986604286022844204804240
340282346638528859811704183484516925440.000000


En fait, l'affichage des flottants n'est vraiment pas une sinécure, la plupart des implémentations standards (Glibc, libc de FreeBSD, etc) sont juste atroce à lire :-°
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 15:35:32

Citation : Mr21

Le nombre d'étoiles dans un code n'augmente pas son skill hein ^^ c'est quoi cette manie de mettre des doubles pointeur partout?
(on en parlait hier justement)


C'est un choix, je préfère faire :
static enum flag_t get_flags_ (const char **str) ;
enum flag_t flags = get_flags_ (&format) ;

que :
const char *get_flags_ (enum flag_t *flag) ;
enum flag_t flags ;
format = get_flags_ (&flags) ;

Le premier me parait plus intuitif, j'ai une fonction get_flags, elle me renvoie un flag. Après je suis d'accord que *++*s n'est pas forcément la chose la plus lisible au premier abord, mais ce n'est pas non plus incompréhensible.

J'ai fait un édit du code, avec une grosse modif sur la représentation des flottants, si certains veulent tester :
my_printf("%12.1f\n", 2164.96545) ;
printf("%12.1f\n", 2164.96545) ;
my_printf("%12.13f\n", 2164.96545) ;
printf("%12.13f\n", 2164.96545) ;
my_printf("%12.13e\n", 2164.96545) ;
printf("%12.13e\n", 2164.96545) ;

# Sortie :
      2165.0 # le mien
      2165.0 # standard
2164.1564000000000 # le mien
2164.1563999999999 # standard (bouh !)
2.16441564000000e+003 # le mien
2164441564000000e+003 # standard


@Taurre, d'après mes "tests", le nombre affiché par printf standard n'est même pas correct, vu que d'après DBL_DIG, le nombre maximum de digit représentable pour un double en mémoire est 15. Mais je suis d'accord avec toi que c'est extrêmement complexe.

Edit : Je fais un édit pour mes dires ci dessus. En gros, que ce soit avec mon printf ou le printf standard, tu peux afficher FLT_MAX, mais DANS LES 2 CAS, tous les chiffres ne seront pas forcément correct. Les seuls chiffres corrects seront les (sur ma machine) 15 premiers. Je confirme que c'est plus que complexe de se plonger dedans... J'ai trouvé une solution qui me semble très correcte vu qu'elle représente bien les chiffres, après je ne sais pas ce que dit le standard quand au reste de la représentation...
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 15:44:43

Ah okay, je pensais encore à des complications inutiles, effectivement là c'est cool!
(j'avais pas vu que le pointeur se déplacait)
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 16:27:54

J'ai édité le code en prenant en compte les remarques de tout à l'heure, je suis toujours ouvert à tout autres remarques :)

J'ai ajouté la gestion du format %n, j'ai modifié la gestion des formats flottants pour qu'elle soit plus cohérente (elle n'est pas cohérente avec le format standard tout le temps, mais elle n'altère pas l'informations, cf. mon post au dessus).

J'ai modifié le format %g, mais la version standard me laisse perplexe donc je ne sais trop que faire... :
double a = 46 ;
printf("%g\n", a);
my_printf("%g\n", a);
printf("%.g\n", a) ;
my_printf("%.g\n", a) ;

46 # std
46 # me, ok
5e+001 # std :/
46 # me
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 17:12:21

Citation : Holt

@Taurre, d'après mes "tests", le nombre affiché par printf standard n'est même pas correct, vu que d'après DBL_DIG, le nombre maximum de digit représentable pour un double en mémoire est 15. Mais je suis d'accord avec toi que c'est extrêmement complexe.



Sur une architecture respectant la norme IEEE 754, le nombre maximum de chiffres décimaux représentables sans erreur d'arrondi est effectivement de 15 (pour un double). Cependant, dans le cas de FLT_MAX, il n'y a pas d'erreur d'arrondi car le nombre est la somme de toutes les puissances de deux de 2104 à 2127, ce qui est tout à fait représentable dans un float (et donc dans un double).

Tu peux d'ailleurs faire le test en comparant l'affichage de cet valeur via la commande bc et via la fonction printf, tu verras que les deux sont rigoureusement identiques ;)

#include <float.h>
#include <stdio.h>


int
main(void)
{
	printf("%f\n", FLT_MAX);
	return 0;
}


$ bc
i = 104;
n = 0;
while (i < 128) {
n += 2^i;
i += 1;
}
n
340282346638528859811704183484516925440

$ gcc main.c -o x
$ ./x
340282346638528859811704183484516925440.000000
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 17:24:57

Exact, en fait le problème viens de la division par 10 qui rend le nombre non stockable intégralement...

Edit : Je viens d'essayer une nouvelle version, à peu près 100 fois plus gourmande, mais qui donne des résultats plus corrects en théorie... Je la peaufine et je la poste :) Ou pas :p
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 23:06:40

Citation : Mr21

Holt, pourquoi malloc toussa pour memmove?



memmove gère les cas où les deux chaines s'entrelacent, contrairement à memcpy. Donc l'implémentation doit prendre ça en compte, et c'est peut être la raison pour le malloc.

Je poste pour suivre la discussion :)

Edit : grave faute :euh: !
  • Partager sur Facebook
  • Partager sur Twitter
2 août 2012 à 23:15:53

Citation : uknow

Citation : Mr21

Holt, pourquoi malloc toussa pour memmove?



memmove gère les cas où les deux chaines s'entre-lassent, contrairement à memcpy. Donc l'implémentation doit prendre ça en compte, et c'est peut être la raison pour le malloc.

Je poste pour suivre la discussion :)


Effectivement, c'était pour ça :) Mais il se trouve que c'est très (trop) inapproprié ici : c'est long, et on ne peut rien faire si le malloc plante...

J'ai rapidement changé mon code, il suffit de faire un test sur les pointeurs pour savoir dans quel sens faire la copie :)
  • Partager sur Facebook
  • Partager sur Twitter
3 août 2012 à 16:14:03

Citation : Holt


il suffit de faire un test sur les pointeurs pour savoir dans quel sens faire la copie



S'ils sont du même tableau OK, mais s'ils sont différents les comparer est un comportement indéfini.

Mais bon, ça fonctionnerait quand même :) .
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 0:53:56

Qu'est ce que cela aurait d'indéterminé?
Un pointeur c'est juste un int comme les autres donc on peut les comparer tout simplement.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 1:12:21

Citation : Mr21

Qu'est ce que cela aurait d'indéterminé?
Un pointeur c'est juste un int comme les autres donc on peut les comparer tout simplement.



Indéfini et pas indéterminé.

Ensuite, un pointeur n'est pas "juste un int", et comme tout autre opérateur, >(=) et <(=) sont définis pour certains opérandes et pas pour tout et n'importe quoi :

Citation : C99 : 6.5.8 Relational operators


When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object or incomplete types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.



Citation : C99 : Undefined behavior

Pointers that do not point to the same aggregate or union (nor just beyond the same array object) are compared using relational operators



Quant au pourquoi du comment, je suppose que c'est parce que, comparer deux pointeurs (avec > et <) qui ne font pas parti du même agrégat est insignifiant et même insensé.
En tout cas, et pour une raison de généricité, la norme n'a jamais dit/exigé que les pointeurs soient des entiers. Mais elle se contente de définir le comportement de chaque opérateur lorsqu'un ou les deux opérandes sont des pointeurs.
Et quand le comportement est indéfini, ça dépendra de l'implémentation, ou même de la machine utilisée.

En tout cas, pour le cas du memmove ça marchera sans problème, pour la raison suivante :

- Si les deux pointeurs font partie du même tableau, ça fonctionne on est tous d'accord.
- Si les deux ne font pas parti du même tableau, que ce soit le if ou le else qui est exécuté ça revient au même, donc le résultat sera bon dans les deux cas.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 1:36:32

Ah donc il n'y a aucun soucis? ^^

Mais tu dis qu'il serait possible d'avoir deux pointeurs qui auraient la même valeur mais qui ne pointeraient pas sur le même objet c'est ça?

En bref dans quel cas l'arithmétique des pointeurs serait indéfini, ou indeterminé ou passur.

Sur le SDZ j'ai l'impression qu'absolument rien n'est stable avec vous, jamais, pourtant y'a jamais de problème.
(ceci dit j'en apprend tous les jours :D)
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 1:47:12

Citation : Mr21

Ah donc il n'y a aucun soucis? ^^



Oui je l'ai dit dans mon post. Mais j'ai fait remarqué un comportement indéfini au passage. J'espère que tu n'as rien contre ça ?

Citation : Mr21

Mais tu dis qu'il serait possible d'avoir deux pointeurs qui auraient la même valeur mais qui ne pointerai pas sur le même objet c'est ça?



Je ne sais pas comment tu as fait pour comprendre ça :o

Citation : Mr21

En bref dans quel cas l'arithmétique des pointeurs serait indéfini, ou indeterminé ou passur.



On ne parle pas d'arithmétique des pointeurs ici, mais si tu tiens à connaitre les cas indéfinis bonne recherche.

Citation : Mr21

Sur le SDZ j'ai l'impression qu'absolument rien n'est stable avec vous, jamais, pourtant y'a jamais de problème.
(ceci dit j'en apprend tous les jours :D)



Il y a plusieurs types de programmeurs vois-tu, ceux qui codent pour la machine sur laquelle ils sont, et sont contents quand ça marche, mais se demandent pourquoi ça marche pas lorsqu'ils envoient leur code à un ami, et ceux qui font attention à la norme et qui n'ont pas autant de surprises. Donc choisis ton camps, et quelque soit ton choix, évite d'imposer ta façon de faire, on est sur un forum, et une analyse de portabilité peut toujours intéresser.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 2:07:54

Jamais je ferais un code qui ne marchera pas sur une machine.. c'est pas gentil de m'accuser de ça :(
Et ou donne-je de mauvais conseils à des gens?

Tout le monde fais un memmove avec un if, ça marchera partout?
T'as dis qu'il y'avait un problème lié au fait de manipuler des pointeurs ou je ne sais quoi, alors.. quel est ce problème? avec un code et non un texte que je ne comprend pas ce soir.

Citation

Je ne sais pas comment tu as fait pour comprendre ça

Je sais pas, j'essaye de comprendre quel pourrait être le problème.
Qu'est ce que des pointeurs dans un même tableau déjà?
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 12:55:19

Citation : Mr21

Qu'est ce que des pointeurs dans un même tableau déjà?



Le passage de la norme cité par uknow précise que le comportement des opérateurs <, <=, > et >= est indéfini dans le cas où deux pointeurs référencent deux objets ne faisant pas partie d'un même agrégat (tableau, structure ou union). Au fond, c'est assez logique, puisque pour le reste la comparaison n'aurait pas beaucoup de sens ;)

Citation : Mr21

Sur le SDZ j'ai l'impression qu'absolument rien n'est stable avec vous, jamais, pourtant y'a jamais de problème.
(ceci dit j'en apprend tous les jours :D)



Ben, disons que la plupart des habitués du forum C essayent de maximiser la portabilité des solutions proposées plutôt que de suggérer des codes limités à certains OS ou architectures. C'est d'ailleurs ce que j'apprécie, entre autre, sur ce forum ^^

Citation : Mr21

Tout le monde fais un memmove avec un if, ça marchera partout?



A priori, je dirais que non. Avec une solution comme celle-là :

void *memmove (void *dest, const void *src, size_t num) {
    unsigned char *destc = dest;
    const unsigned char *srcc = src ;
    if (dest <= src) {
	for (; num > 0; num--, destc++, srcc++) {
	    *destc = *srcc ;
	}
    }
    else {
	srcc += (num - 1);
	destc += (num - 1);
	for (; num > 0; num--, destc--, srcc--) {
	    *destc = *srcc ;
	}
    }
    return dest ;
}


Il me semble qu'il reste le cas tordu où les objets se chevauchent, mais uniquement au niveau d'un ou plusieurs byte(s) ou bit(s) et où la comparaison n'a pas un comportement déterminé. Une solution parfaitement portable me semblerait être la suivante :

void *
memmove(void * dst, void * src, size_t len)
{
	unsigned char * tmp = malloc(len);

	if (tmp != NULL) {
		unsigned char * p = (unsigned char *)dst;
		unsigned char * q = (unsigned char *)src;

		for (size_t i = 0; i < len; ++i)
			tmp[i] = q[i];

		for (size_t i = 0; i < len; ++i)
			p[i] = tmp[i];

		free(tmp);
	}

	return dst;
}


Mais bon, c'est plus lourd et il y a le problème de l'allocation dynamique qui peut échouer.

EDIT : je n'ai rien dit, il n'y a pas de soucis avec la solution de Holt :-°
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 13:58:58

Vous vous doutez bien que si memmove avait une chance de rater ce serait écrit dans le man, non?
C'est évident que ça n'utilise pas malloc, en tout cas ça me paraît évident.


Citation

Le passage de la norme cité par uknow précise que le comportement des opérateurs <, <=, > et >= est indéfini dans le cas où deux pointeurs référencent deux objets ne faisant pas partie d'un même agrégat (tableau, structure ou union).

il se passe quoi si ce sont deux objets différents? il y aura bien une valeur différente dans chaque pointeur jsuis pas fou, cette valeur peut être affiché traité calculé incrémenté etc. c'est un nombre, donc on peut savoir si il est supérieur ou pas à un autre.


Citation

Il me semble qu'il reste le cas tordu où les objets se chevauchent, mais uniquement au niveau d'un ou plusieurs byte(s) ou bit(s) et où la comparaison n'a pas un comportement déterminé. Une solution parfaitement portable me semblerait être la suivante :

bah si ça se chevauche de plusieurs octets c'est la raison pour laquelle la fonction est là.

Mais ça ne peut pas se chevaucher de quelques bit.
L'unité la plus ptite est un octet. sinon faudrait des pointeurs à virgule.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 14:45:54

Citation : Mr21

Vous vous doutez bien que si memmove avait une chance de rater ce serait écrit dans le man, non?
C'est évident que ça n'utilise pas malloc, en tout cas ça me paraît évident.



Cela paraîtrait logique, en effet :-°

Citation : Mr21

il se passe quoi si ce sont deux objets différents? il y aura bien une valeur différente dans chaque pointeur jsuis pas fou, cette valeur peut être affiché traité calculé incrémenté etc. c'est un nombre, donc on peut savoir si il est supérieur ou pas à un autre.



Oui, la seule chose que dit la norme c'est que le résultat n'est pas défini en dehors des objets appartenant à un même agrégat. Autrement dit, tu ne peux faire aucune déduction du résultat que tu obtiendras, c'est tout (la position des objets dans la pile, ou que sais-je).

Citation : Mr21

bah si ça se chevauche de plusieurs octets c'est la raison pour laquelle la fonction est là.



Hum... En effet :honte:

Citation : Mr21

Mais ça ne peut pas se chevaucher de quelques bit.
L'unité la plus ptite est un octet. sinon faudrait des pointeurs à virgule.



La plus petite unité adressable est effectivement le byte, ce que j'ai dit n'a donc pas de sens puisque memmove reçoit des pointeurs comme paramètres. Mais la plus petite unité pouvant contenir des données (et donc le plus petit objet possible) est bien le bit.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 16:58:49

Citation : Mr21

il se passe quoi si ce sont deux objets différents? il y aura bien une valeur différente dans chaque pointeur jsuis pas fou, cette valeur peut être affiché traité calculé incrémenté etc. c'est un nombre, donc on peut savoir si il est supérieur ou pas à un autre.



Deux pointeurs sont égaux lorsqu'ils référencent le même objet. Hormis ce cas là ils ne sont pas égaux.

On peut effectivement faire des opérations dessus mais en utilisant des opérateurs dont le comportement est défini pour des opérandes de type pointeurs.

Si tu remarques, la norme définit l'incrémentation d'un pointeur par un déplacement dans un tableau, et pas "incrémenter un pointeur de 1, revient à ajouter la taille de son type à sa valeur".

La soustraction n'est définie que pour deux pointeurs du même tableau + une case après ce tableau. et pas n'importe quels pointeurs.

En ce qui est de l'affichage d'un pointeur, voici ce que dit la norme :

Citation : 7.19.6.1 fprintf function - §8

p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.



"Deux pointeurs du même tableau" sont deux pointeurs qui référencent deux éléments du même tableau.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 17:35:34

haha j'étais venu pour voir un peu le sujet et je suis complétement largué dans tout vos codes XD (je ne suis informaticien, mais je code des programmes de simulations en méca flu)

Bonne chance en tout cas !!

p.s. je retourne sur mes problèmes de pointeurs... ;)
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 18:43:45

Citation : uknow

Deux pointeurs sont égaux lorsqu'ils référencent le même objet. Hormis ce cas là ils ne sont pas égaux.

Evidemment :p

Citation : uknow

On peut effectivement faire des opérations dessus mais en utilisant des opérateurs dont le comportement est défini pour des opérandes de type pointeurs.

Il se passe quoi si ce n'est pas défini? '<' et '>' ne le sont pas?

Citation : uknow

Si tu remarques, la norme définit l'incrémentation d'un pointeur par un déplacement dans un tableau, et pas "incrémenter un pointeur de 1, revient à ajouter la taille de son type à sa valeur".

Oui 'fin t'as beau sortir du tableau ça s’incrémentera toujours de son sizeof.
D'où les "invalid read of size 8" de valgrind par exemple.

Citation : uknow

La soustraction n'est définie que pour deux pointeurs du même tableau + une case après ce tableau. et pas n'importe quels pointeurs.

Oo ça voudrait dire qu'il est possible de savoir la taille d'un tableau en C?

Citation : uknow

En ce qui est de l'affichage d'un pointeur, voici ce que dit la norme :<citation nom="7.19.6.1 fprintf function - §8">p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.

printf converti les nombre en chaînes de caractère? voilà une grosse nouvelle ^^
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 19:49:18

Citation : Mr21

Oo ça voudrait dire qu'il est possible de savoir la taille d'un tableau en C?



Oui, il suffit d'utiliser l'opérateur sizeof, tout simplement :p
Plus sérieusement, cela signifie simplement que le type ptrdiff_t doit pouvoir contenir la taille du plus grand objet allouable, qui correspond à la différence entre l'adresse de la première et de la dernière case (plus un) du tableau.

Enfin, ça c'est la théorie, parce que sous GNU/Linux 32 bits, tu peux bizarrement alloué un tableau de char dont la taille dépasse la capacité du type ptrdiff_t...

Citation : uknow

printf converti les nombre en chaînes de caractère? voilà une grosse nouvelle ^^



Je sens un brin d'ironie mal placée dans cette phrase :-°
Ce que uknow voulait souligné, c'est la différence entre l'explication du format "%d" :

Citation : C11 (n1570) § 7.21.6.1 the fprintf function al 8 p 312

The int argument is converted to signed decimal in the style [−]dddd. The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it is expanded with leading zeros. The default precision is 1. The result of converting a zero value with a precision of zero is no characters.



et le format "%p" :

Citation : C11 (n1570) § 7.21.6.1 the fprintf function al 8 p 315

The argument shall be a pointer to void. The value of the pointer isconverted to a sequence of printing characters, in an implementation-defined manner.



tu remarqueras que le format "%p" laisse une grand libertée à l'implémentation, qui pourrait par exemple afficher les pointeurs sous forme d'un couple index:décalage ou que sais-je encore.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 20:06:32

%d tu voulais dire %x plutôt non?
Et j'ai jamais vu de différence, y'en a une?

Donc c'est quand exactement qu’incrémenter (ou décrémenter) un pointeur de type int* p rajouterai que 1 et non sizeof(int)?

Et oui j'ironise parce que j'y comprend plus rien en fait. Mais je sous-estime personne hein, juste que j'aimerai voir un problème en forme de code plutôt qu'une citation obscure d'une norme obscure etc.
  • Partager sur Facebook
  • Partager sur Twitter
4 août 2012 à 21:15:55

Citation : Mr21

%d tu voulais dire %x plutôt non?



Non, je paralis bien de "%d", mais j'aurais effectivement pu prendre n'importe quel autre format entier en exemple.

Citation : Mr21

Et j'ai jamais vu de différence, y'en a une ?



Avec les implémentations les plus courantes, il me semble que l'affichage des formats "%x" et "%p" est effectivement identique.

Citation : Mr21

Donc c'est quand exactement qu’incrémenter (ou décrémenter) un pointeur de type int* p rajouterai que 1 et non sizeof(int)?



Je pense qu'il y a un malentendu entre uknow et toi de ce côté, à moins de faire des conversions, c'est impossible étant donné l'arithmétique des pointeurs.

Citation : Mr21

Et oui j'ironise parce que j'y comprend plus rien en fait. Mais je sous-estime personne hein, juste que j'aimerai voir un problème en forme de code plutôt qu'une citation obscure d'une norme obscure etc.



De ce côté, je n'en sais pas vraiment plus. Ce que je sais, c'est que la norme est évasive au sujet de la représentation des pointeurs et qu'il doit y avoir une bonne raison à cela. Sinon, histoire d'avoir plus d'informations (et surtout un peu plus de concret), je viens de poser une question sur fr.comp.lang.c, n'hésite pas à y participer ;)
  • Partager sur Facebook
  • Partager sur Twitter
5 août 2012 à 0:21:46

Citation : Mr21


Donc c'est quand exactement qu’incrémenter (ou décrémenter) un pointeur de type int* p rajouterai que 1 et non sizeof(int)?



quand sizeof int fera 1.
je ne suis pas sur d'avoir compris ton problème, mais peut être la réponse est dans la définition des opérateurs + et -:

Citation : c99

For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type



certains passages de la norme sont effectivement obscures mais ceux que je t'ai montrés ne le sont pas je trouve.
  • Partager sur Facebook
  • Partager sur Twitter
5 août 2012 à 2:13:13

Taurre merci :) t'as posé les mêmes questions que moi.
On verra les réponses.

Ce que dit le gars qui a reply ne semble plus a jour si?
Il mentionne des pointeurs différents qui pointeraient sur la même chose.

"8086" si il parle de ça :
http://fr.wikipedia.org/wiki/Intel_8086
Est-ce encore d'actualité?


  • Partager sur Facebook
  • Partager sur Twitter