Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

long & 64 bits

29 réponses
Avatar
alian
Ave,

J'ai un probleme avec cet algo de calcul de crc32 sur ia64:
long crc = 0xFFFFFFFF;
if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^ ((long) crc32tab[(crc ^ (*buf)) &
0xff]);
buf++;
len--;
}
}

Le (long) vient me mettre la grouille et j'ai aucune idee comment
corriger ca. Est ce que qqn a une idee ? Pis comme je suis une chiasse,
si je pouvais avoir l'explication theorique avec ... Parce que que je
me dise que le long fait 8 bits, ben ca me change pas grand chose ...

sur ia64:
./a.out TEST
O=EEEA93B8

sur i386:
./a.out TEST
O=11156C47

Voici le programme de test complet, a compiler avec juste g++
monfichier.c, a tester avec ./a.out monmot :

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <string>
#include <iostream>
using namespace std;

#define LIMITED_32(x) ((x) & 0xFFFFFFFF)

static const unsigned long crc32tab[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

long Signed_CRC32(const char *buf, size_t len) {
long crc = 0xFFFFFFFF;

if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^ ((long) crc32tab[(crc ^ (*buf)) &
0xff]);
buf++;
len--;
}
}

return LIMITED_32(~crc);
}

int main(int argc, char** argv)
{
std::string param(argv[1]);
long value = Signed_CRC32(param.c_str(), param.size());
printf("O=%lX\n", value);
}

10 réponses

1 2 3
Avatar
Pierre Maurette
Ave,

J'ai un probleme avec cet algo de calcul de crc32 sur ia64:
long crc = 0xFFFFFFFF;
if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^ ((long) crc32tab[(crc ^ (*buf)) &
0xff]);
buf++;
len--;
}
}

Le (long) vient me mettre la grouille et j'ai aucune idee comment
corriger ca. Est ce que qqn a une idee ? Pis comme je suis une chiasse,
si je pouvais avoir l'explication theorique avec ... Parce que que je
me dise que le long fait 8 bits, ben ca me change pas grand chose ...
A première vue, votre code n'est pas portable, en ce sens qu'il suppose

un long de 32 bits, sizeof(long)==4.
Remplacez long par un type à taille fixe de 32 bits. A mon avis en
unsigned. S'il n'existe pas, vous le fabriquez, avec des #if, les
constantes de limits.h, et des typedef.


sur ia64:
./a.out TEST
OîEA93B8

sur i386:
./a.out TEST
O156C47

Voici le programme de test complet, a compiler avec juste g++
monfichier.c, a tester avec ./a.out monmot :
Bien de poster un code compilable. Même si c'est du C++ ;-) Notez que

ce n'est pas grave, la question telle qu'elle est posée au dessus est
en charte. En fait, c'est une gfonction C que vous utilisez en C++, je
suppose.

--
Pierre Maurette

Avatar
alian
Ca marche avec -1 en effet, un cast avec (int) au lieu de (long), et
l'utilisation de LIMITED_32 ...
Et ia64, oui c'est de l'itanium (4 proc a 2400 et 8Go de Ram, oui ca
compile bien :-)
Avatar
Blaise Potard
wrote:
Ave,

J'ai un probleme avec cet algo de calcul de crc32 sur ia64:
long crc = 0xFFFFFFFF;
if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^ ((long) crc32tab[(crc ^ (*buf)) &
0xff]);
buf++;
len--;
}
}

Le (long) vient me mettre la grouille et j'ai aucune idee comment
corriger ca. Est ce que qqn a une idee ? Pis comme je suis une chiasse,
si je pouvais avoir l'explication theorique avec ... Parce que que je
me dise que le long fait 8 bits, ben ca me change pas grand chose ...


Il faut dire que ton code est un peu osé, il suppose implicitement qu'un
long est codé sur 32 bits. Bon, en remplaçant ta première ligne par
'long crc = -1' ça devrait tomber en marche.

L'explication est relativement simple, quand on y pense : ton algo de
calcul du crc suppose que ta variable crc est initialisée avec un nombre
ne contenant que des 1 en binaire, et en l'initialisant à 0xFFFFFFFF ça
marche avec des long sur 32 bits, mais pas avec des long plus grands,
tout simplement, donc pas sur une archi qui a des long sur 64 bits. Bon,
maintenant que j'y pense, il n'est pas impossible que mon hack ne marche
pas sur des architecture ou le -1 n'est pas codé par '0b11...11', mais :

1) je pense que de toute manière l'algo ne fonctionerait plus du tout
2) est-ce que ça existe vraiment (encore) ce genre d'archi ?

P.S.: Quand tu parles d'ia64, tu parles de x86-64, ou de l'Itanium ?
Simple curiosité.

Avatar
Pierre Maurette
[...]
tu peux corriger un peu plus proprement en utilisant un cast vers
int32_t, ou alors tu peux déclarer ton tableau en int32_t (ce qui te
permet d'économiser un peu de place en mémoire, de te débarasser du
cast, et en plus c'est un peu plus logique). Il faut probablement
ajouter un #include <inttypes.h>
inttypes.h, et plus précisément stdint.h, est C99. Donc, pas C++, sauf

à utiliser la bibliothèque Boost (cstdint.hpp). Sinon, il faut donc
soit utiliser des entiers à taille fixe propres à l'implémentation,
soit les fabriquer.

--
Pierre Maurette

Avatar
Antoine Leca
En news:,
alian va escriure:
J'ai un probleme avec cet algo de calcul de crc32 sur ia64:
long crc = 0xFFFFFFFF;


unsigned long, à tout le moins. Tu ne veux *pas* de propagation de signe...


if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^
((long) crc32tab[(crc ^ (*buf)) & 0xff]);


À quoi sert ce (long) ? crc32tab est un unsigned long, et c'est exactement
ce que l'on veut ici, une valeur *non* signée.

À l'intérieur des crochets, nous voulons obtenir une valeur entre 0 et 255.
*buf devrait (si les choses étaient intelligement faites) être un unsigned
char, donc être étendu à unsigned long pour faire l'opération ^ ; le
résultat sera ensuite réduit par le masque 0xFF à l'intervalle désiré, tout
va bien de ce côté-là.

Et si long est sur 48 bits, me diriez-vous ? et bien pas de souci, comme les
propriétés de l'arithmétique non signée ne se propagent pas en dehors de son
domaine de définition pour les opérations comme ^ ou >>.


buf++; len--; }
}

Le (long) vient me mettre la grouille et j'ai aucune idee comment
corriger ca.


Peut être en l'enlevant ?



Voici le programme de test complet, a compiler avec juste g++
monfichier.c, a tester avec ./a.out monmot :

#include <iostream>
using namespace std;


Hmmm...


static const unsigned long crc32tab[256] = {


Un bon point : crc32tab est un unsigned long...


long Signed_CRC32(


Pourquoi retourner un signed long ? C'est quoi, un CRC32 négatif ?

const char *buf, size_t len) {


J'espère pour toi que char est garanti pur porc non signé, parce que sinon,
cela va mettre encore plus le désordre...



long crc = 0xFFFFFFFF;


unsigned long, j'espère avoir été clair.


if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^ ((long) crc32tab


Et là tu supprimes purement et simplement le transtypage.


Antoine

Avatar
Antoine Leca
En news:,
Pierre Maurette va escriure:
Ave,

J'ai un probleme avec cet algo de calcul de crc32 sur ia64:
long crc = 0xFFFFFFFF;
if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^ ((long) crc32tab[(crc ^ (*buf)) &
0xff]);
buf++;
len--;
}
}

A première vue, votre code n'est pas portable, en ce sens qu'il

suppose un long de 32 bits, sizeof(long)==4.


Où ?
(Le même code, à peine corrigé, doit fonctionner avec sizeof(long)==2, avec
des char sur 16 bits, en supposant bien sûr que les données de la trame ont
été rangées un octet par byte; mais là je suis d'accord que c'est pour faire
joujou.)


Remplacez long par un type à taille fixe de 32 bits.


Et si tu n'en as pas ?

A mon avis en unsigned.


Là oui, cela risque d'aider.



Antoine


Avatar
Blaise Potard
wrote:
Ca marche avec -1 en effet, un cast avec (int) au lieu de (long), et
l'utilisation de LIMITED_32 ...


Arf, tu as tout à fait raison, j'avais oublié que le problème
d'extension de signe touchait aussi les éléments de ton tableau
crc32tab. La solution de mettre un cast à int résout le problème de
façon un peu crade (tu supposes implicitement que sizeof int = 32 bits),
tu peux corriger un peu plus proprement en utilisant un cast vers
int32_t, ou alors tu peux déclarer ton tableau en int32_t (ce qui te
permet d'économiser un peu de place en mémoire, de te débarasser du
cast, et en plus c'est un peu plus logique). Il faut probablement
ajouter un #include <inttypes.h> (mais là on est revenu à la solution de
Pierre Maurette, en fait).

Et ia64, oui c'est de l'itanium (4 proc a 2400 et 8Go de Ram, oui ca
compile bien :-)


La classe :-)

Avatar
Pierre Maurette
En news:,
Pierre Maurette va escriure:
Ave,

J'ai un probleme avec cet algo de calcul de crc32 sur ia64:
long crc = 0xFFFFFFFF;
if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^ ((long) crc32tab[(crc ^ (*buf)) &
0xff]);
buf++;
len--;
}
}

A première vue, votre code n'est pas portable, en ce sens qu'il

suppose un long de 32 bits, sizeof(long)==4.


Où ?
(Le même code, à peine corrigé, doit fonctionner avec sizeof(long)==2, avec
des char sur 16 bits, en supposant bien sûr que les données de la trame ont
été rangées un octet par byte; mais là je suis d'accord que c'est pour faire
joujou.)
Je suis allé un peu vite sans étudier le code (je me promettais de le

faire plus tard). En passant, tu coupe/quote allègrement, et sans
marque de coupure. Je répondais en fait sous le commentaire plus qu'au
code. Disons que comme un mauvais toubib, je me suis laissé influencer
par le diagnostic suggéré par le patient ;-) Et peut-être par crc*32*.
Je n'ai jamais codé de crc. J'ai pensé que ça exigeait des "exact width
interger".


Remplacez long par un type à taille fixe de 32 bits.


Et si tu n'en as pas ?
...."A mon avis en unsigned. S'il n'existe pas, vous le fabriquez, avec

des #if, les constantes de limits.h, et des typedef."

--
Pierre Maurette



Avatar
Antoine Leca
En news:e094er$rkk$, Antoine Leca (moi) va escriure:
En news:,
Pierre Maurette va escriure:
A première vue, votre code n'est pas portable, en ce sens qu'il
suppose un long de 32 bits, sizeof(long)==4.


Où ?


OK, ça y est, j'ai vu. Le code est trafiqué pour générer une valeur bizarre
qui correspond en gros à l'algorithme classique du CRC32, mais transporté en
signé en supposant une machine sur 32 bits. Effectivement, le code résultant
n'est plus portable.


Remplacez long par un type à taille fixe de 32 bits.
A mon avis en unsigned.



Bin, si tu fais cela, tu reviens à l'algorithme normal du CRC32, qui lui
*est* portable ;-)


Antoine


Avatar
Antoine Leca
En news:e0948e$qog$, Antoine Leca va escriure:
En news:,
alian va escriure:
J'ai un probleme avec cet algo de calcul de crc32 sur ia64:
long crc = 0xFFFFFFFF;


unsigned long, à tout le moins. Tu ne veux *pas* de propagation de
signe...


Au temps pour moi : en fait, l'algorithme a *besoin* des propriétés
spécifiques des entiers en complément à 2 sur machine 32 bits....


if (buf != NULL) {
while (len > 0) {
crc = (crc >> 8) ^
((long) crc32tab[(crc ^ (*buf)) & 0xff]);


À quoi sert ce (long) ? crc32tab est un unsigned long, et c'est
exactement ce que l'on veut ici, une valeur *non* signée.


Celui-là, par contre, je ne pense pas qu'il soit nécessaire, on doit pouvoir
l'enlever. La valeur sera la même, et donc l'effet de l'opération ^ ne
changera pas.


Et si long est sur 48 bits, me diriez-vous ? et bien pas de souci,
comme les propriétés de l'arithmétique non signée ne se propagent pas
en dehors de son domaine de définition pour les opérations comme ^ ou
.




Cela prouve que celui qui a écrit cela n'avait rien compris !


const char *buf, size_t len) {


J'espère pour toi que char est garanti pur porc non signé, parce que
sinon, cela va mettre encore plus le désordre...


En fait non, parce qu'après l'opération ^crc (qui est identique en
complément à 2), il y a un masque des 8 bits de poids faible, donc que char
soit signé ou pas est sans effet.

(ce qui est le cas de l'algorithme initial, d'ailleurs ;-)).


long crc = 0xFFFFFFFF;


unsigned long, j'espère avoir été clair.


Hmmm hmm. Voili voilou. Cancel, n'est-ce pas. Merci.



Un des problèmes quand même, c'est que je n'arrive pas à vérifier
l'algorithme (manque de jeu d'essai, de référence.)


Antoine



1 2 3