Enfin, le meilleur pour la fin: l'équivalent en floating point ne marche pas... quand je caste b[w] en long double, j'ai gcc qui se roule en position foetale et couine "error: invalid operands to binary <<
Je dirai plutôt qu'il te tape sur les doigts pour avoir essayé une chose infâme. En effet, la norme impose que les deux arguments d'un opérateur de décalage soient des entiers:
6.5.7 Bitwise shift operators
Syntax
1 shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
Constraints
2 Each of the operands shall have integer type.
Et de surcroît, dès que je caste mes binaires en float/double ils deviennent tout corrompu de l'intérieur, alors que si je me contente de les copier en tant qu'entier ça passe !
Tu peux être plus précis ? Tu obtiens quoi comme résultat, précisément ? Et en quoi ça n'est pas ce que tu veux ?
while (w --) ret += (long long) b[w] << w * 8;
J'ai un doute, là... Tu ne serais pas, par hasard, en train de supposer qu'un unsigned char fait 8 bits ?
Tu définis ta fonction comme retournant un unsigned long long et ensuite tu définis ret comme un long long... Ca tombe bien, vu que le code de ta fonction fait que ret pourra contenir une valeur négative ! (bah oui, s'il y a débordement : overflow sur un entier signé, ça peut faire des dégâts collatéraux) Et la conversion d'un entier signé contenant une valeur négative en un entier non-signé se fait modulo le max de l'entier non signé +1 (cf. 6.3.1.3.-2)
D'où:
unsigned long long ret = 0;
/* ... */
while (w --)
{
ret += ((unsigned long long) b[w]) << (w * CHAR_BIT);
}
en castant vers un type non signé (c'est plus sûr et évite les comportements indéfinis de certaines limites), et en (sur)parenthésant afin de bien voir ce qu'on fait (toujours faire attention aux règles de priorité des opérateurs...)
J'ai aussi un "invalid storage class" pour _fetch_float() (la même chose qu'au dessus mais avec des casts en fait :) ) si je lui fait renvoyer un long double...
Cf. 6.3.1.4-2; je présume que le domaine de valeurs de long long déborde celle de long double sur ton environnement... et donc, quand tu retournes le contenu de ret, il n'est pas garanti que la conversion se fasse (je n'ai pas trouvé si la norme spécifie que cette conversion doit être ok ou non. Je suppose que c'est undefined...) Ca ne serait pas plus simple de définir ret comme un long double dans ce cas ? Ca éviterait des prises de tête à calculer les écarts entre les bornes de <limits.h>...
# Hack de vfscanf(3), quelques réponses
Posté par alf . En réponse au message Hack de vfscanf(3), 4 questions. Évalué à 3.
Tu peux être plus précis ? Tu obtiens quoi comme résultat, précisément ? Et en quoi ça n'est pas ce que tu veux ?
J'ai un doute, là... Tu ne serais pas, par hasard, en train de supposer qu'un unsigned char fait 8 bits ?
Tu définis ta fonction comme retournant un unsigned long long et ensuite tu définis ret comme un long long... Ca tombe bien, vu que le code de ta fonction fait que ret pourra contenir une valeur négative ! (bah oui, s'il y a débordement : overflow sur un entier signé, ça peut faire des dégâts collatéraux) Et la conversion d'un entier signé contenant une valeur négative en un entier non-signé se fait modulo le max de l'entier non signé +1 (cf. 6.3.1.3.-2)
D'où:
unsigned long long ret = 0;
/* ... */
while (w --)
{
ret += ((unsigned long long) b[w]) << (w * CHAR_BIT);
}
en castant vers un type non signé (c'est plus sûr et évite les comportements indéfinis de certaines limites), et en (sur)parenthésant afin de bien voir ce qu'on fait (toujours faire attention aux règles de priorité des opérateurs...)
Cf. 6.3.1.4-2; je présume que le domaine de valeurs de long long déborde celle de long double sur ton environnement... et donc, quand tu retournes le contenu de ret, il n'est pas garanti que la conversion se fasse (je n'ai pas trouvé si la norme spécifie que cette conversion doit être ok ou non. Je suppose que c'est undefined...) Ca ne serait pas plus simple de définir ret comme un long double dans ce cas ? Ca éviterait des prises de tête à calculer les écarts entre les bornes de <limits.h>...