On 17 nov, 15:48, candide wrote:Donc, si j'ai bien compris, plus efficace car qsort copiera alors des
adresses plutôt que des (éventuellement grosses) structures ?
C'est un principe général. Organiser ses données pour que les
manipulations concernent des pointeurs et non des blocs de données
importants (disons > 10 x la taille d'un pointeur[1]) fait partie du
B.A. BA de la programmation efficace...
[1] A la place de Plaugher, plutôt qu'un 256 en dur, j'aurais mis (64
* sizeof (void *)) pour exprimer cette intention et la traduire de
façon portable...
On 17 nov, 15:48, candide <cand...@free.invalid> wrote:
Donc, si j'ai bien compris, plus efficace car qsort copiera alors des
adresses plutôt que des (éventuellement grosses) structures ?
C'est un principe général. Organiser ses données pour que les
manipulations concernent des pointeurs et non des blocs de données
importants (disons > 10 x la taille d'un pointeur[1]) fait partie du
B.A. BA de la programmation efficace...
[1] A la place de Plaugher, plutôt qu'un 256 en dur, j'aurais mis (64
* sizeof (void *)) pour exprimer cette intention et la traduire de
façon portable...
On 17 nov, 15:48, candide wrote:Donc, si j'ai bien compris, plus efficace car qsort copiera alors des
adresses plutôt que des (éventuellement grosses) structures ?
C'est un principe général. Organiser ses données pour que les
manipulations concernent des pointeurs et non des blocs de données
importants (disons > 10 x la taille d'un pointeur[1]) fait partie du
B.A. BA de la programmation efficace...
[1] A la place de Plaugher, plutôt qu'un 256 en dur, j'aurais mis (64
* sizeof (void *)) pour exprimer cette intention et la traduire de
façon portable...
Pour swapper deux variables de même type, il suffit de swapper leurs
représentations physiques, ce qu'on peut effectuer par le cast en type
unsigned. Soit deux variables d'un type quelconque et 'ent' le type
entier non signé de même taille.
Pas compris ce qu'est ent. Si le type "quelconque" est, au hasard,
struct toto
{
int a;
char b;
void *c;
double z[24];
};
c'est quoi "le type entier non signé de même taille" ?
Pour swapper deux variables de même type, il suffit de swapper leurs
représentations physiques, ce qu'on peut effectuer par le cast en type
unsigned. Soit deux variables d'un type quelconque et 'ent' le type
entier non signé de même taille.
Pas compris ce qu'est ent. Si le type "quelconque" est, au hasard,
struct toto
{
int a;
char b;
void *c;
double z[24];
};
c'est quoi "le type entier non signé de même taille" ?
Pour swapper deux variables de même type, il suffit de swapper leurs
représentations physiques, ce qu'on peut effectuer par le cast en type
unsigned. Soit deux variables d'un type quelconque et 'ent' le type
entier non signé de même taille.
Pas compris ce qu'est ent. Si le type "quelconque" est, au hasard,
struct toto
{
int a;
char b;
void *c;
double z[24];
};
c'est quoi "le type entier non signé de même taille" ?
Pierre Maurette a écrit :Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
On le trouve ici :
http://graphics.stanford.edu/~seander/bithacks.html#SwappingValuesSubAdd
Pierre Maurette a écrit :
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
On le trouve ici :
http://graphics.stanford.edu/~seander/bithacks.html#SwappingValuesSubAdd
Pierre Maurette a écrit :Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
On le trouve ici :
http://graphics.stanford.edu/~seander/bithacks.html#SwappingValuesSubAdd
ld a écrit :
c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Rien compris.
ld a écrit :
c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Rien compris.
ld a écrit :
c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Rien compris.
c'est quoi "le type entier non signé de même taille" ?
Comme souvent, j'ai du mal à croire à la sincérité de votre candeur.
Il
faut que le type entier correspondant existe,
unsigned. Soit deux variables d'un TYPE QUELCONQUE et 'ent' le type
c'est quoi "le type entier non signé de même taille" ?
Comme souvent, j'ai du mal à croire à la sincérité de votre candeur.
Il
faut que le type entier correspondant existe,
unsigned. Soit deux variables d'un TYPE QUELCONQUE et 'ent' le type
c'est quoi "le type entier non signé de même taille" ?
Comme souvent, j'ai du mal à croire à la sincérité de votre candeur.
Il
faut que le type entier correspondant existe,
unsigned. Soit deux variables d'un TYPE QUELCONQUE et 'ent' le type
In article <4928b2c6$0$30916$,
candide wrote:ld a écrit :c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Rien compris.
Comme quoi, essayer de comprendre le C en lisant juste la norme et en
la brandissant telle la sainte bible n'est pas forcement une bonne idee...
La norme fait tres attention de ne pas trop parler directement d'alignement...
Une machine normale possede de la memoire, avec des adresses, qui ont une
structure plus ou moins fantaisiste, qui conduisent a l'abstraction "pointeur"
dans la norme. Une deuxieme abstraction, c'est char, qui (normalement)
correspond a la plus petite valeur adressable independamment par le processeur,
avec comme contrainte supplementaire que les caracteres doivent faire au
moins 8 bits (et donc que c'est mort pour les proc 4 bits...)
La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Tu constateras que la norme reclame que malloc fasse un truc magique, a savoir
te renvoyer un pointeur qui peut adresser n'importe quoi.
Rien compris
In article <4928b2c6$0$30916$426a74cc@news.free.fr>,
candide <candide@free.invalid> wrote:
ld a écrit :
c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Rien compris.
Comme quoi, essayer de comprendre le C en lisant juste la norme et en
la brandissant telle la sainte bible n'est pas forcement une bonne idee...
La norme fait tres attention de ne pas trop parler directement d'alignement...
Une machine normale possede de la memoire, avec des adresses, qui ont une
structure plus ou moins fantaisiste, qui conduisent a l'abstraction "pointeur"
dans la norme. Une deuxieme abstraction, c'est char, qui (normalement)
correspond a la plus petite valeur adressable independamment par le processeur,
avec comme contrainte supplementaire que les caracteres doivent faire au
moins 8 bits (et donc que c'est mort pour les proc 4 bits...)
La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Tu constateras que la norme reclame que malloc fasse un truc magique, a savoir
te renvoyer un pointeur qui peut adresser n'importe quoi.
Rien compris
In article <4928b2c6$0$30916$,
candide wrote:ld a écrit :c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Rien compris.
Comme quoi, essayer de comprendre le C en lisant juste la norme et en
la brandissant telle la sainte bible n'est pas forcement une bonne idee...
La norme fait tres attention de ne pas trop parler directement d'alignement...
Une machine normale possede de la memoire, avec des adresses, qui ont une
structure plus ou moins fantaisiste, qui conduisent a l'abstraction "pointeur"
dans la norme. Une deuxieme abstraction, c'est char, qui (normalement)
correspond a la plus petite valeur adressable independamment par le processeur,
avec comme contrainte supplementaire que les caracteres doivent faire au
moins 8 bits (et donc que c'est mort pour les proc 4 bits...)
La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Tu constateras que la norme reclame que malloc fasse un truc magique, a savoir
te renvoyer un pointeur qui peut adresser n'importe quoi.
Rien compris
La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Exemple "concret" de déréférencement interdit ?
La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Exemple "concret" de déréférencement interdit ?
La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Exemple "concret" de déréférencement interdit ?
In article <49298b4d$0$13205$,
candide wrote:La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Exemple "concret" de déréférencement interdit ?
adresse memoire non multiple de 4, dereferencee en temps que int* ou assimile
sur une sparc, ou un alpha -> bus error.
sur un 68000, pointeur sur un entier ou un short impair -> bus error.
sur un 68010 ou plus -> trap et acces deux fois plus lent que la normale.
sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
In article <49298b4d$0$13205$426a34cc@news.free.fr>,
candide <candide@free.invalid> wrote:
La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Exemple "concret" de déréférencement interdit ?
adresse memoire non multiple de 4, dereferencee en temps que int* ou assimile
sur une sparc, ou un alpha -> bus error.
sur un 68000, pointeur sur un entier ou un short impair -> bus error.
sur un 68010 ou plus -> trap et acces deux fois plus lent que la normale.
sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
In article <49298b4d$0$13205$,
candide wrote:La plupart des architectures possedent de plus des contraintes d'alignement:
des qu'on veut acceder a une valeur plus grosse qu'un caractere (mettons un
entier sur 4 octets pour filer les idees), ca marche vachement mieux si
l'adresse est "alignee", a savoir un multiple de 2 ou 4... tout betement
parce qu'en vrai, les acces a la memoire se font a travers un bus de N, 32
ou 64 bits, et que, pour simplifier la logique et pouvoir mettre plus de
memoire, le bus en question ne livre ses donnees que par blocs de N bits
bien alignes. Sur les archi merdiques genre intel, il y a du bazar en plus
dans le processeur pour detecter les acces non alignes (au detriment de
la vitesse) et rapatrier deux mots memoire au lieu d'un. Sur les archi
decentes, genre sparc ou alpha, ca fait une bus error...
Donc, si tu as une collection de char contigus en memoire, apres avoir
caste le pointeur sur le premier vers un type plus gros, c'est pas du tout
garanti que tu pourras dereferencer ce pointeur pour en sortir quelque chose.
Exemple "concret" de déréférencement interdit ?
adresse memoire non multiple de 4, dereferencee en temps que int* ou assimile
sur une sparc, ou un alpha -> bus error.
sur un 68000, pointeur sur un entier ou un short impair -> bus error.
sur un 68010 ou plus -> trap et acces deux fois plus lent que la normale.
sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
On 2008-11-23, Marc Espie wrote:sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
A noter que pour les personnes n'ayant qu'un x86 sous la main,
et voulant traquer les pb d'alignement, il semble qu'on puisse
dire au processeur de générer un "Bus error".
Mais ça dépend visiblement de certains paramètres de config.
J'avais le code suivant:
int main(){
char t[sizeof(double)*2];
double* d= (double*) (t+1);
__asm__("pushfl; popl %eax; orl $0x40000,%eax; pushl %eax; popfl;");
*d= 1.0;
return 0;
}
qui me faisait un beau message d'erreur sur ma précédente machine,
et qui ne dit plus rien sur la nouvelle (toutes deux des x86 sous
Linux, complio gcc).
J'ai la flemme de chercher le comment du pourquoi, mais ça peut
faire une piste de travail pour qui s'y intéresse.
On 2008-11-23, Marc Espie <espie@lain.home> wrote:
sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
A noter que pour les personnes n'ayant qu'un x86 sous la main,
et voulant traquer les pb d'alignement, il semble qu'on puisse
dire au processeur de générer un "Bus error".
Mais ça dépend visiblement de certains paramètres de config.
J'avais le code suivant:
int main(){
char t[sizeof(double)*2];
double* d= (double*) (t+1);
__asm__("pushfl; popl %eax; orl $0x40000,%eax; pushl %eax; popfl;");
*d= 1.0;
return 0;
}
qui me faisait un beau message d'erreur sur ma précédente machine,
et qui ne dit plus rien sur la nouvelle (toutes deux des x86 sous
Linux, complio gcc).
J'ai la flemme de chercher le comment du pourquoi, mais ça peut
faire une piste de travail pour qui s'y intéresse.
On 2008-11-23, Marc Espie wrote:sur un intel, adresse non multiple de 4: lenteur... en particulier cote
pile et valeurs flottantes.
A noter que pour les personnes n'ayant qu'un x86 sous la main,
et voulant traquer les pb d'alignement, il semble qu'on puisse
dire au processeur de générer un "Bus error".
Mais ça dépend visiblement de certains paramètres de config.
J'avais le code suivant:
int main(){
char t[sizeof(double)*2];
double* d= (double*) (t+1);
__asm__("pushfl; popl %eax; orl $0x40000,%eax; pushl %eax; popfl;");
*d= 1.0;
return 0;
}
qui me faisait un beau message d'erreur sur ma précédente machine,
et qui ne dit plus rien sur la nouvelle (toutes deux des x86 sous
Linux, complio gcc).
J'ai la flemme de chercher le comment du pourquoi, mais ça peut
faire une piste de travail pour qui s'y intéresse.