CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

ça sert a quoi les const, unsigned ?

PocoIo
PocoIo
Niveau 10
01 novembre 2013 à 16:30:36

Pour donner un exemple plus concret :

int f(int n)
{
return n/4;
}

Pour cette fonction le compilateur me génère le code assembleur suivant :

mov eax,dword ptr [ebp+8]
cdq
and edx,3
add eax,edx
sar eax,2

Alors que si je change le "int n" en "unsigned int n", j'obtiens le code assembleur suivant :

mov eax,dword ptr [ebp+8]
shr eax,2

Avec unsigned le compilateur se contente d'un simple décalage.

godrik
godrik
Niveau 30
01 novembre 2013 à 17:11:40

en effet compile en -O3 avec icc 14, je n'obtiens pas le meme code non plus. En signed:

movl %edi, %eax #3.10
sarl $1, %eax #3.10
shrl $30, %eax #3.10
addl %edi, %eax #3.10
sarl $2, %eax #3.10
ret #3.10

en unsigned:

shrl $2, %edi #3.10
movl %edi, %eax #3.10
ret #3.10

ryviel
ryviel
Niveau 5
01 novembre 2013 à 18:11:23

Tellement longtemps que je n'ai pas vu Chris_27 sur le forum, cela fait plaisir de voir qu'il est toujours autant en forme :D

chris_27
chris_27
Niveau 10
01 novembre 2013 à 18:36:28

PocoIo : Ok, mais dans ce cas l'opération n'est pas la même si n est signed ou unsigned (la faute à la sémantique du C :( ). Si n est unsigned, n/4 fait la division euclidienne de n par 4. Mais si c'est un signed, l'opération n'est plus une division euclidienne (le quotient est arrondi vers 0, alors qu'il est arrondi vers le bas dans une division euclidienne).

En tout cas :
1. Le shift arithmétique correspond parfaitement à la division euclidienne sur des entiers signés.
2. Dans un contexte plus gros (ou après inlining), le compilo va redécouvrir tout seul qu'on pouvait s'en sortir avec une division euclidienne et donc réduire l'assembleur correspondant à un appel à sar.
3. Changer le signe de n dans ton exemple va changer la sémantique du code, donc possiblement introduire des bugs.

godrik
godrik
Niveau 30
01 novembre 2013 à 19:28:51

Moralement, je pense qu'un shift arithmetique devrait suffir. Alors pourquoi le compilateur ajoute d'autres instructions?

chris_27
chris_27
Niveau 10
01 novembre 2013 à 19:36:32

Parce que la sémantique du C pue, essentiellement. Enfin, c'est pas nouveau. Quelqu'un a déjà soulevé à juste titre le fait que l'encodage (complément à 1 ou à 2) des négatifs n'était pas imposé dans les standards du langage.

En math (où le reste d'une division est toujours positif), -11/3 ça fait -4 et il reste +1.

En circuiterie/assembleur, on fait comme en math (le complément à 2 a été choisi pour coller à l'arithmétique modulaire, après tout).

En C, -11/3 ça fait -3 et il reste -2. FAIL. :(

PocoIo
PocoIo
Niveau 10
01 novembre 2013 à 20:11:14

" En circuiterie/assembleur, on fait comme en math "

Pourtant l'instruction idiv arrondi aussi vers 0, comme en C.

chris_27
chris_27
Niveau 10
01 novembre 2013 à 21:47:37

idiv n'est pas une instruction réelle, c'est du microcode qui prend des dizaines de cycles à s'exécuter.

PocoIo
PocoIo
Niveau 10
01 novembre 2013 à 22:24:55

Cela-dit il me semblait que, de façon générale en informatique (et pas que en C), pour la division entière on cherche à arrondir vers 0 notamment pour éviter que la valeur absolue du quotient soit différente et que par exemple :

-(11/3) soit différent de (-11)/3

chris_27
chris_27
Niveau 10
03 novembre 2013 à 14:00:01

Je cite mon ancienne prof de bio : "N'utilise pas les mots [car] et [parce que], ils ne permettent pas de faire un raisonnement scientifique valide".

elite: 1+2 ne me permet pas de ccnclure quoi que ce soit, vu qye idiv n'est pas une vraie instruction. Mais tu aurais pu convaincre en tournant ta phrase autrement et en utilisant un "donc". Essaie, tu verras que ça marche beaucoup mieux. :-)))

Sinon, je parlais d'optims de type propagation de constantes au sein d'une fonction. Après, j'avoue que vu le code en question (dont la taille n'a fait que chuter depuis que je suis dessus), je n'ai pas eu le courage de chercher précisément pourquoi gcc arrivait à optimiser ça de façon aussi flagrante. :honte:

godrik
godrik
Niveau 30
03 novembre 2013 à 17:43:05

mmm, tout ca, ce sont des utilisations de const qui (moralement) remplace un #define ou un parametre template.

Mais l'utilisation principale des const en C++ n'est pas la. C'est typiquement de passer un pointeur vers une donne constant (ou un reference mais en l'occurence ca ne change rien). Et la ce n'est pas que la donnee est constante au sein de tout le programme, ca veut juste dire que la fonction courrante ne peut pas le changer. Et ca, je ne pense par que ca ammene une optimisation quelconque. Does it?

Pseudo supprimé
Pseudo supprimé 04 novembre 2013 à 13:37:55

"1+2 ne me permet pas de ccnclure quoi que ce soit, vu qye idiv n'est pas une vraie instruction"

je comprends pas, tu veux dire quoi par la ?

chris_27
chris_27
Niveau 10
05 novembre 2013 à 11:19:37

Que la seule conclusion logique après lecture de ton explication est qu'on se fout des shift vu qu'il suffit de faire un idiv.

Et j'espère qu'on est d'accord pour dire que c'est tout sauf la bonne conclusion à tirer. :(

Pseudo supprimé
Pseudo supprimé 07 novembre 2013 à 06:31:04

on est d'accord. je voulais seulement dire qu'on peut pas remplacer idiv par un simple sift a cause de l’arrondi vers 0. exemple avec /2

  1. define div2(val) (val >> 1)
  2. define idiv2(val) ((val+1) >> 1)

assert( div2(-13) == -13/2 ) // erreur
assert( idiv2(-13) == -13/2 ) // ok

apres va savoir pourquoi idiv arrondi vers 0 (c'est la même chose avec ARM)

PocoIo
PocoIo
Niveau 10
07 novembre 2013 à 14:13:17

" apres va savoir pourquoi idiv arrondi vers 0 (c'est la même chose avec ARM) "

Je pense que c'est pour la raison que j'ai énoncé plus haut, à savoir pour éviter que :

" -(11/3) soit différent de (-11)/3 "

Sous forums
  • Aide à l'achat Mac
  • Internet
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment