Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
Le 05-10-2010, Yann Renard a écrit :Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include<stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Et non. Tu as une opération qui implique un signé et un non signé
de même taille. Il faut donc faire une conversion, soit du signé en
non signé, soit du non signé en signé.
La norme dit que c'est le signé qui sera convertit en non signé
(donc surement 2^64 - 6 dans ton cas). Puis on divise par 5.
Puis on convertit le non signé en signé (ce qui se faite sans modif
de la valeur).Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
gcc a surement plein de bugs, mais sans optimisation, sur une
architecture répandue et sur un code si simple, je pense qu'on
peut lui faire confiance.
Marc Boyer
Le 05-10-2010, Yann Renard<yann.renard@irisa.nospam.fr> a écrit :
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include<stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Et non. Tu as une opération qui implique un signé et un non signé
de même taille. Il faut donc faire une conversion, soit du signé en
non signé, soit du non signé en signé.
La norme dit que c'est le signé qui sera convertit en non signé
(donc surement 2^64 - 6 dans ton cas). Puis on divise par 5.
Puis on convertit le non signé en signé (ce qui se faite sans modif
de la valeur).
Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
gcc a surement plein de bugs, mais sans optimisation, sur une
architecture répandue et sur un code si simple, je pense qu'on
peut lui faire confiance.
Marc Boyer
Le 05-10-2010, Yann Renard a écrit :Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include<stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Et non. Tu as une opération qui implique un signé et un non signé
de même taille. Il faut donc faire une conversion, soit du signé en
non signé, soit du non signé en signé.
La norme dit que c'est le signé qui sera convertit en non signé
(donc surement 2^64 - 6 dans ton cas). Puis on divise par 5.
Puis on convertit le non signé en signé (ce qui se faite sans modif
de la valeur).Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
gcc a surement plein de bugs, mais sans optimisation, sur une
architecture répandue et sur un code si simple, je pense qu'on
peut lui faire confiance.
Marc Boyer
On 10/05/2010 03:44 PM, Marc Boyer wrote:
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
On 10/05/2010 03:44 PM, Marc Boyer wrote:
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
On 10/05/2010 03:44 PM, Marc Boyer wrote:
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Le 05-10-2010, Yann Renard a écrit :
> On 10/05/2010 03:44 PM, Marc Boyer wrote:
>
> J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Le 05-10-2010, Yann Renard <yann.renard@irisa.nospam.fr> a écrit :
> On 10/05/2010 03:44 PM, Marc Boyer wrote:
>
> J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Le 05-10-2010, Yann Renard a écrit :
> On 10/05/2010 03:44 PM, Marc Boyer wrote:
>
> J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Or j'obtiens 3689348814741910322.
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Or j'obtiens 3689348814741910322.
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Or j'obtiens 3689348814741910322.
On 10/05/2010 03:44 PM, Marc Boyer wrote:Le 05-10-2010, Yann Renard a écrit :Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include<stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Et non. Tu as une opération qui implique un signé et un non signé
de même taille. Il faut donc faire une conversion, soit du signé en
non signé, soit du non signé en signé.
La norme dit que c'est le signé qui sera convertit en non signé
(donc surement 2^64 - 6 dans ton cas). Puis on divise par 5.
Puis on convertit le non signé en signé (ce qui se faite sans modif
de la valeur).Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
gcc a surement plein de bugs, mais sans optimisation, sur une
architecture répandue et sur un code si simple, je pense qu'on
peut lui faire confiance.
Marc Boyer
Merci Marc pour cette réponse rapide.
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Bonne journée,
Yann
On 10/05/2010 03:44 PM, Marc Boyer wrote:
Le 05-10-2010, Yann Renard<yann.renard@irisa.nospam.fr> a écrit :
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include<stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Et non. Tu as une opération qui implique un signé et un non signé
de même taille. Il faut donc faire une conversion, soit du signé en
non signé, soit du non signé en signé.
La norme dit que c'est le signé qui sera convertit en non signé
(donc surement 2^64 - 6 dans ton cas). Puis on divise par 5.
Puis on convertit le non signé en signé (ce qui se faite sans modif
de la valeur).
Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
gcc a surement plein de bugs, mais sans optimisation, sur une
architecture répandue et sur un code si simple, je pense qu'on
peut lui faire confiance.
Marc Boyer
Merci Marc pour cette réponse rapide.
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Bonne journée,
Yann
On 10/05/2010 03:44 PM, Marc Boyer wrote:Le 05-10-2010, Yann Renard a écrit :Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include<stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%llin", c);
return 0;
}
Et non. Tu as une opération qui implique un signé et un non signé
de même taille. Il faut donc faire une conversion, soit du signé en
non signé, soit du non signé en signé.
La norme dit que c'est le signé qui sera convertit en non signé
(donc surement 2^64 - 6 dans ton cas). Puis on divise par 5.
Puis on convertit le non signé en signé (ce qui se faite sans modif
de la valeur).Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
gcc a surement plein de bugs, mais sans optimisation, sur une
architecture répandue et sur un code si simple, je pense qu'on
peut lui faire confiance.
Marc Boyer
Merci Marc pour cette réponse rapide.
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Bonne journée,
Yann
Marc Boyer writes:Le 05-10-2010, Yann Renard a écrit :
> On 10/05/2010 03:44 PM, Marc Boyer wrote:
>
> J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Il y a d'abord un choix de privilegier la valeur (autrement dit si le type
signe est capable de representer toutes les valeurs du type non signe,
c'est le type signe qui est utilise).
Ensuite, quand il n'y a pas un type capable de representer tout
l'intervalle possible de l'autre, utiliser le type non signe a l'avantage
d'etre toujours bien defini
Marc Boyer <Marc.Boyer@cert.onera.fr.invalid> writes:
Le 05-10-2010, Yann Renard <yann.renard@irisa.nospam.fr> a écrit :
> On 10/05/2010 03:44 PM, Marc Boyer wrote:
>
> J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Il y a d'abord un choix de privilegier la valeur (autrement dit si le type
signe est capable de representer toutes les valeurs du type non signe,
c'est le type signe qui est utilise).
Ensuite, quand il n'y a pas un type capable de representer tout
l'intervalle possible de l'autre, utiliser le type non signe a l'avantage
d'etre toujours bien defini
Marc Boyer writes:Le 05-10-2010, Yann Renard a écrit :
> On 10/05/2010 03:44 PM, Marc Boyer wrote:
>
> J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Il y a d'abord un choix de privilegier la valeur (autrement dit si le type
signe est capable de representer toutes les valeurs du type non signe,
c'est le type signe qui est utilise).
Ensuite, quand il n'y a pas un type capable de representer tout
l'intervalle possible de l'autre, utiliser le type non signe a l'avantage
d'etre toujours bien defini
Oui, préférer le bug reproductible à une éventuelle bizarrerie sur une
architecture exotique. C'est très "C" comme approche. ;-)
Oui, préférer le bug reproductible à une éventuelle bizarrerie sur une
architecture exotique. C'est très "C" comme approche. ;-)
Oui, préférer le bug reproductible à une éventuelle bizarrerie sur une
architecture exotique. C'est très "C" comme approche. ;-)
Le 05-10-2010, Yann Renard a écrit :J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Il a l'avantage de produire le débordement sur de petites valeurs
négatives, que l'on voit vite sur des tests unitaires, alors que
le choix contraire ne l'aurait fait apparaître sur de grandes valeurs,
que pas grand monde ne teste (jusqu'au jour où la fusée explose ;-) ).
Il a l'inconvénient de faire planter plein de code qui de toutes
façons ne manipuleront jamais de grandes valeurs (genre du nombre
de trimestres de cotisation d'un salarié ;-) ).
Mais un grand ancien va bien passer par là nous expliquer les enjeux
et l'histoire de ce choix.
Le 05-10-2010, Yann Renard <yann.renard@irisa.nospam.fr> a écrit :
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Il a l'avantage de produire le débordement sur de petites valeurs
négatives, que l'on voit vite sur des tests unitaires, alors que
le choix contraire ne l'aurait fait apparaître sur de grandes valeurs,
que pas grand monde ne teste (jusqu'au jour où la fusée explose ;-) ).
Il a l'inconvénient de faire planter plein de code qui de toutes
façons ne manipuleront jamais de grandes valeurs (genre du nombre
de trimestres de cotisation d'un salarié ;-) ).
Mais un grand ancien va bien passer par là nous expliquer les enjeux
et l'histoire de ce choix.
Le 05-10-2010, Yann Renard a écrit :J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Il a l'avantage de produire le débordement sur de petites valeurs
négatives, que l'on voit vite sur des tests unitaires, alors que
le choix contraire ne l'aurait fait apparaître sur de grandes valeurs,
que pas grand monde ne teste (jusqu'au jour où la fusée explose ;-) ).
Il a l'inconvénient de faire planter plein de code qui de toutes
façons ne manipuleront jamais de grandes valeurs (genre du nombre
de trimestres de cotisation d'un salarié ;-) ).
Mais un grand ancien va bien passer par là nous expliquer les enjeux
et l'histoire de ce choix.
Marc Boyer écrivit :Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Cela me semble pourtant logique : le problème est l'étendue des valeurs
donc le nombre de bits, qui est la vraie limite. Et avec les nombres non
signés (qui représentent des adresses ou des tailles), on approche plus
les bornes qu'avec les nombres signés, qui sont plus généralistes.
Cela dans le contexte de la décision initiale, celle de DMR quand il y
introduit unsigned en 1972. Quelques années plus tard, au moment de la
norme ANSI, un autre facteur est venu compliquer la situation, la
possibilité d'avoir des entiers non signés avec diverses
représentations, dont certaines créant des situations d'exceptions sur
débordement : la possibilité de pouvoir définir un ensemble cohérent de
règles privilégiant les nombres signés sur les non signés sont devenues
quasiment nulles (dans le contexte de C). De ce fait, le comité a opté
pour l'affirmation de règles très claires sur les nombres non signés
(qui doivent impérativement utiliser l'arithmétique modulo n), et les
entiers signés suivent comme ils peuvent.
Il a l'avantage de produire le débordement sur de petites valeurs
négatives, que l'on voit vite sur des tests unitaires, alors que
le choix contraire ne l'aurait fait apparaître sur de grandes valeurs,
que pas grand monde ne teste (jusqu'au jour où la fusée explose ;-) ).
Remarque que le problème des grandes valeurs est peut-être estompé à ce
niveau, mais il reste pour l'opérateur * (et à un moindre niveau <<).
Il a l'inconvénient de faire planter plein de code qui de toutes
façons ne manipuleront jamais de grandes valeurs (genre du nombre
de trimestres de cotisation d'un salarié ;-) ).
Si tu as du code qui manipule des nombres de trimestres ou équivalent en
non signé, ÀMHA le souci ce n'est pas que cela va planter, ce n'est même
pas que la conception est complètement à revoir, c'est qu'il faut
d'urgence changer l'analyste-programmeur ;-) Le fait d'utiliser des
types non signés fait effectivement gagner quelques valeurs dans
l'intervalle (et c'était très important il y a quelques années avec les
quantités 16 bits) mais le prix à payer ce sont des conversions
intempestives.
De ce fait, les programmeurs C apprennent vite à se
méfier des unsigned qui traînent, puis par ricochet des sizeof() et
autres size_t qui importent le même effet.
Mais un grand ancien va bien passer par là nous expliquer les enjeux
et l'histoire de ce choix.
Je sens comme une tentative (ratée) d'éviter les commentaires...
Marc Boyer écrivit :
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Cela me semble pourtant logique : le problème est l'étendue des valeurs
donc le nombre de bits, qui est la vraie limite. Et avec les nombres non
signés (qui représentent des adresses ou des tailles), on approche plus
les bornes qu'avec les nombres signés, qui sont plus généralistes.
Cela dans le contexte de la décision initiale, celle de DMR quand il y
introduit unsigned en 1972. Quelques années plus tard, au moment de la
norme ANSI, un autre facteur est venu compliquer la situation, la
possibilité d'avoir des entiers non signés avec diverses
représentations, dont certaines créant des situations d'exceptions sur
débordement : la possibilité de pouvoir définir un ensemble cohérent de
règles privilégiant les nombres signés sur les non signés sont devenues
quasiment nulles (dans le contexte de C). De ce fait, le comité a opté
pour l'affirmation de règles très claires sur les nombres non signés
(qui doivent impérativement utiliser l'arithmétique modulo n), et les
entiers signés suivent comme ils peuvent.
Il a l'avantage de produire le débordement sur de petites valeurs
négatives, que l'on voit vite sur des tests unitaires, alors que
le choix contraire ne l'aurait fait apparaître sur de grandes valeurs,
que pas grand monde ne teste (jusqu'au jour où la fusée explose ;-) ).
Remarque que le problème des grandes valeurs est peut-être estompé à ce
niveau, mais il reste pour l'opérateur * (et à un moindre niveau <<).
Il a l'inconvénient de faire planter plein de code qui de toutes
façons ne manipuleront jamais de grandes valeurs (genre du nombre
de trimestres de cotisation d'un salarié ;-) ).
Si tu as du code qui manipule des nombres de trimestres ou équivalent en
non signé, ÀMHA le souci ce n'est pas que cela va planter, ce n'est même
pas que la conception est complètement à revoir, c'est qu'il faut
d'urgence changer l'analyste-programmeur ;-) Le fait d'utiliser des
types non signés fait effectivement gagner quelques valeurs dans
l'intervalle (et c'était très important il y a quelques années avec les
quantités 16 bits) mais le prix à payer ce sont des conversions
intempestives.
De ce fait, les programmeurs C apprennent vite à se
méfier des unsigned qui traînent, puis par ricochet des sizeof() et
autres size_t qui importent le même effet.
Mais un grand ancien va bien passer par là nous expliquer les enjeux
et l'histoire de ce choix.
Je sens comme une tentative (ratée) d'éviter les commentaires...
Marc Boyer écrivit :Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Cela me semble pourtant logique : le problème est l'étendue des valeurs
donc le nombre de bits, qui est la vraie limite. Et avec les nombres non
signés (qui représentent des adresses ou des tailles), on approche plus
les bornes qu'avec les nombres signés, qui sont plus généralistes.
Cela dans le contexte de la décision initiale, celle de DMR quand il y
introduit unsigned en 1972. Quelques années plus tard, au moment de la
norme ANSI, un autre facteur est venu compliquer la situation, la
possibilité d'avoir des entiers non signés avec diverses
représentations, dont certaines créant des situations d'exceptions sur
débordement : la possibilité de pouvoir définir un ensemble cohérent de
règles privilégiant les nombres signés sur les non signés sont devenues
quasiment nulles (dans le contexte de C). De ce fait, le comité a opté
pour l'affirmation de règles très claires sur les nombres non signés
(qui doivent impérativement utiliser l'arithmétique modulo n), et les
entiers signés suivent comme ils peuvent.
Il a l'avantage de produire le débordement sur de petites valeurs
négatives, que l'on voit vite sur des tests unitaires, alors que
le choix contraire ne l'aurait fait apparaître sur de grandes valeurs,
que pas grand monde ne teste (jusqu'au jour où la fusée explose ;-) ).
Remarque que le problème des grandes valeurs est peut-être estompé à ce
niveau, mais il reste pour l'opérateur * (et à un moindre niveau <<).
Il a l'inconvénient de faire planter plein de code qui de toutes
façons ne manipuleront jamais de grandes valeurs (genre du nombre
de trimestres de cotisation d'un salarié ;-) ).
Si tu as du code qui manipule des nombres de trimestres ou équivalent en
non signé, ÀMHA le souci ce n'est pas que cela va planter, ce n'est même
pas que la conception est complètement à revoir, c'est qu'il faut
d'urgence changer l'analyste-programmeur ;-) Le fait d'utiliser des
types non signés fait effectivement gagner quelques valeurs dans
l'intervalle (et c'était très important il y a quelques années avec les
quantités 16 bits) mais le prix à payer ce sont des conversions
intempestives.
De ce fait, les programmeurs C apprennent vite à se
méfier des unsigned qui traînent, puis par ricochet des sizeof() et
autres size_t qui importent le même effet.
Mais un grand ancien va bien passer par là nous expliquer les enjeux
et l'histoire de ce choix.
Je sens comme une tentative (ratée) d'éviter les commentaires...