• [^] # Re: C++ type et performances

    Posté par . En réponse au message pre-realease de battle-rage un jeu de combat a la street fighter.. Évalué à 2. Dernière modification le 23 octobre 2016 à 19:48.

    Le complément à deux est simplement la représentation binaire d'un entier négatif. Le truc c'est qu'en utilisant cette représentation une addition n'a pas besoin de tester le signe des opérantes. Au niveau du cpu, cela ne change strictement rien, il n'y pas de test supplémentaire, d'ailleurs comment ferait-il pour faire la différence entre une valeur signée d'une non signée ?? Pour le prouver il suffit de créer un fichier signed.c qui contient la fonction "int monadd(int a, int b) { return a+b;}", tu fais de même avec unsigned.c "unsigned int monadd(unsigned a, unsigned b) {return a+b;}", tu compiles avec gcc -save-temps -c unsigned.c, tu regarde le fichier assembleur .s et tu verras qu'il n'y a aucune différence. Comme je l'ai dit, ce qu'il peut y avoir comme différence serait du à une décision de l'optimisateur de gcc qui pourrait supprimer du code. Donc bref, tu mets unsigned si c'est effectivement le domaine de ta variable, c'est très bien mais ça ne changera strictement rien en ce qui concerne la rapidité d'exécution.

    Par contre il ne faut jamais assigner un unsigned vers un signed ou inversément. Le language C admet cela en tant que cast implicite, si tu as de la chance ton compilateur t'arvertira, ou pas... Parce ça peut avoir de fâcheuses conséquences et est une source de problèmes de sécurité à cause des overflows et des optimisations. Malheureusement c'est un peu plus compliqué à expliquer de manière succinte.

    Pour en revenir au int8 vs int. Si tu utilises des int8s sans padding (ce que tu sembles vouloir faire car pour pouvoir économiser de la mémoire), tu vas imposer de facto des lectures non-alignées car l'adresse de ta variable ne tombera pas toujours sur un multiple de 4 octets. Certaines archi imposent d'utiliser une instruction différente ou une série d'instructions pour cela. Grossièrement, elles vont lire la lecture du mot à l'adresse alignée inférieure et faire un shift de bit pour avoir ton octet dans la partie lsb. Encore pire, si tu lis un int32 non aligné (c.-à-d. à cheval sur deux int32 alignés), elle va devoir lire le mot d'en dessous, faire un shit, celui du dessus, faire un shift et enfin combiner les deux moitiées. x86 est "non-alignée" (excepté les instructions style mmx,sse,etc.), ce qui fait que la même instruction marche avec les deux types d'adresse, néanmoins elle reste moins performante avec des adresses non-alignées car la même partie de passe-passe va être faite par le cpu, dans ton dos.

    Ceci dit, ça n'est pas pour cela que c'est une mauvaise idée ou que cela sera toujours moins performant. En effet, la mémoire sauvegardée peut servir à autre chose; par exemple dans un environement restreint type console de jeux, ça peut-être un bon calcul.