Mot-clé «enregistrer» en C?


273

Que fait le registermot-clé en langage C? J'ai lu qu'il est utilisé pour l'optimisation mais n'est clairement défini dans aucune norme. Est-il toujours pertinent et si oui, quand l'utiliseriez-vous?


42
Que fait le mot-clé de registre en C? est ignoré :)
bestsss

19
@bestsss Pas complètement ignoré. Essayez d'obtenir une adresse de registervariable.
qrdl

4
Ce code que vous lisez est ancien youtube.com/watch?v=ibF36Yyeehw#t=1827
Colonel Panic

Réponses:


341

C'est une indication pour le compilateur que la variable sera fortement utilisée et que vous recommandez qu'elle soit conservée dans un registre de processeur si possible.

La plupart des compilateurs modernes le font automatiquement et sont meilleurs à les choisir que nous, les humains.


18
Eh bien, j'ai expérimenté le registre pour modifier mes soumissions ACM, et parfois cela a vraiment aidé. Mais il faut vraiment faire attention, car les mauvais choix dégradent les performances.
ypnos

81
Une bonne raison de ne pas utiliser 'register': vous ne pouvez pas prendre l'adresse d'une variable déclarée 'register'
Adam Rosenfield

23
Notez que certains / plusieurs compilateurs ignoreront complètement le mot clé register (qui est parfaitement légal).
Euro Micelli

5
ypnos: En fait, la vitesse d'une solution aux problèmes ACM ICPC dépend beaucoup plus du choix de l'algorithme que de telles micro-optimisations. Le délai de 5 secondes est généralement suffisant pour une solution correcte, surtout lorsque vous utilisez C au lieu de Java.
Joey

66
@Euro: Vous le savez probablement, mais juste pour être explicite, le compilateur est nécessaire pour empêcher que l'adresse d'une registervariable soit prise; c'est le seul effet obligatoire du registermot - clé. Même cela est suffisant pour améliorer les optimisations, car il devient trivial de dire que la variable ne peut être modifiée que dans cette fonction.
Dale Hagglund

69

Je suis surpris que personne n'ait mentionné que vous ne pouvez pas prendre une adresse de variable de registre, même si le compilateur décide de garder la variable en mémoire plutôt que dans le registre.

Donc, en utilisant registervous ne gagnez rien (de toute façon le compilateur décidera par lui-même où mettre la variable) et perdez l' &opérateur - aucune raison de l'utiliser.


94
Il y a une raison en fait. Le simple fait que vous ne puissiez pas prendre l'adresse de la variable donne des opportunités d'optimisation: le compilateur peut prouver que la variable ne sera pas aliasée.
Alexandre C.

8
Les compilateurs sont notoirement terribles pour prouver que l'aliasing ne se produit pas dans les cas non triviaux, il registerest donc utile pour cela même si le compilateur ne le met pas dans un registre.
Miles Rout

2
@AlexandreC, Miles, les compilateurs sont parfaitement OK pour vérifier si & est pris d'une variable n'importe où. Donc, quelles que soient les autres difficultés liées à la détection de l'aliasing, le retraitement ne vous rapporte rien. Lorsque K + R a créé C pour la première fois, il était en effet utile de savoir à l'avance que & ne serait pas utilisé, car ce compilateur a effectivement pris la décision d'allocation de registre en voyant la déclaration, avant de regarder le code suivant. C'est pourquoi l'interdiction est en place. Le mot-clé «register» est essentiellement obsolète maintenant.
greggo

25
Par cette logique constest également inutile car il ne vous gagne rien, vous perdez seulement la possibilité de changer une variable. registerpourrait être utilisé pour s'assurer que personne ne prendra l'adresse d'une variable à l'avenir sans réfléchir. Je n'ai cependant jamais eu de raison de l'utiliser register.
Tor Klingberg

34

Il indique au compilateur d'essayer d'utiliser un registre CPU, au lieu de RAM, pour stocker la variable. Les registres sont dans le CPU et beaucoup plus rapides d'accès que la RAM. Mais ce n'est qu'une suggestion pour le compilateur, et cela peut ne pas suivre.


8
Ajouter une valeur pour les personnes utilisant C ++, C ++ vous permet de prendre l'adresse d'une variable de registre
Will

5
@Will: ... mais le compilateur finira probablement par ignorer le mot-clé. Voir ma réponse.
bwDraco

Oui, il semble que «register» soit un placebo en C ++, il est juste là pour permettre la compilation du code C en C ++. Et cela n'aurait pas beaucoup de sens d'interdire & var tout en permettant de le passer par référence, ou const-reference, et sans passer par référence, vous avez sérieusement cassé C ++.
greggo

22

Je sais que cette question concerne C, mais la même question pour C ++ a été fermée en tant que doublon exact de cette question. Cette réponse peut donc ne pas s'appliquer à C.


Le dernier projet de la norme C ++ 11, N3485 , le dit dans 7.1.1 / 3:

Un registerspécificateur est un indice de l'implémentation que la variable ainsi déclarée sera largement utilisée. [ note: L'indice peut être ignoré et dans la plupart des implémentations, il sera ignoré si l'adresse de la variable est prise. Cette utilisation est déconseillée ... —fin note ]

En C ++ (mais pas en C), la norme n'indique pas que vous ne pouvez pas prendre l'adresse d'une variable déclarée register; cependant, comme une variable stockée dans un registre CPU tout au long de sa durée de vie n'a pas d'emplacement mémoire associé, la tentative de prendre son adresse serait invalide et le compilateur ignorera le registermot clé pour autoriser la prise de l'adresse.


17

Cela n'a pas été pertinent depuis au moins 15 ans, car les optimiseurs prennent de meilleures décisions à ce sujet que vous ne le pouvez. Même quand c'était pertinent, cela avait beaucoup plus de sens sur une architecture CPU avec beaucoup de registres, comme SPARC ou M68000 que sur Intel avec sa rareté de registres, dont la plupart sont réservés par le compilateur à ses propres fins.


13

En fait, register indique au compilateur que la variable n'a pas d'alias avec quoi que ce soit d'autre dans le programme (pas même les caractères).

Cela peut être exploité par les compilateurs modernes dans diverses situations et peut aider le compilateur dans un code complexe - dans un code simple, les compilateurs peuvent le comprendre par eux-mêmes.

Sinon, il ne sert à rien et n'est pas utilisé pour l'attribution des registres. Il n'entraîne généralement pas de dégradation des performances pour le spécifier, tant que votre compilateur est suffisamment moderne.


"dit au compilateur .." non, ce n'est pas le cas. Toutes les variables automatiques ont cette propriété, sauf si vous prenez son adresse et l' utilisez d'une manière qui dépasse certaines utilisations analysables. Ainsi, le compilateur le sait grâce au code, que vous utilisiez ou non le mot-clé register. Il se trouve que le mot clé «register» rend l'écriture d'une telle construction illégale, mais si vous n'utilisez pas le mot clé et ne prenez pas l'adresse de cette manière, le compilateur sait toujours que c'est sûr. Ces informations sont cruciales pour l'optimisation.
greggo

1
@greggo: Dommage registerinterdit de prendre l'adresse du tout, car sinon il pourrait être utile d'informer les compilateurs des cas où un compilateur pourrait appliquer des optimisations de registre malgré le fait que l'adresse d'une variable soit passée à une fonction externe (la variable devrait être vidé en mémoire pour cet appel particulier , mais une fois la fonction de retour, le compilateur pourrait à nouveau la traiter comme une variable dont l'adresse n'a jamais été prise).
supercat

@supercat Je pense que ce serait encore une conversation très délicate à avoir avec le compilateur. Si c'est ce que vous voulez dire au compilateur, vous pouvez le faire en copiant la première variable dans une seconde qui n'a pas de '&' dessus, puis en n'utilisant plus jamais la première.
greggo

1
@greggo: Dire que si barest une registervariable, un compilateur peut à sa guise remplacer foo(&bar);par int temp=bar; foo(&temp); bar=temp;, mais prendre l'adresse de barserait interdit dans la plupart des autres contextes ne semblerait pas être une règle trop compliquée. Si la variable pouvait autrement être conservée dans un registre, la substitution rendrait le code plus petit. Si la variable devait de toute façon être conservée dans la RAM, la substitution augmenterait le code. Laisser la question de l'opportunité de faire la substitution au compilateur conduirait à un meilleur code dans les deux cas.
supercat

1
@greggo: Permettre une registerqualification sur des variables globales, que le compilateur permette ou non de prendre l'adresse, permettrait de belles optimisations dans les cas où une fonction en ligne qui utilise une variable globale est appelée à plusieurs reprises dans une boucle. Je ne peux pas penser à une autre façon de laisser cette variable dans un registre entre les itérations de boucle - pouvez-vous?
supercat

13

J'ai lu qu'il est utilisé pour l'optimisation mais n'est clairement défini dans aucune norme.

En fait, il est clairement défini par la norme C. Citant le projet de section 6.7.1 N1570 , paragraphe 6 (les autres versions ont le même libellé):

Une déclaration d'un identifiant pour un objet avec un spécificateur de classe de stockage registersuggère que l'accès à l'objet soit aussi rapide que possible. La mesure dans laquelle ces suggestions sont efficaces est définie par la mise en œuvre.

L' &opérateur unaire ne peut pas être appliqué à un objet défini avec registeret registerne peut pas être utilisé dans une déclaration externe.

Il existe quelques autres règles (assez obscures) spécifiques aux registerobjets qualifiés:

  • La définition d'un objet tableau avec registerun comportement indéfini.
    Correction: il est légal de définir un objet tableau avec register, mais vous ne pouvez rien faire d'utile avec un tel objet (l'indexation dans un tableau nécessite de prendre l'adresse de son élément initial).
  • Le _Alignasspécificateur (nouveau dans C11) ne peut pas être appliqué à un tel objet.
  • Si le nom de paramètre transmis à la va_startmacro est registerqualifié, le comportement n'est pas défini.

Il peut y en avoir quelques autres; téléchargez un brouillon de la norme et recherchez «s'inscrire» si vous êtes intéressé.

Comme son nom l'indique, la signification d' origine de registerétait d'exiger qu'un objet soit stocké dans un registre CPU. Mais avec l'amélioration de l'optimisation des compilateurs, cela est devenu moins utile. Les versions modernes de la norme C ne font pas référence aux registres du processeur, car elles ne supposent plus (ont besoin) qu'il existe une telle chose (il existe des architectures qui n'utilisent pas de registres). La sagesse courante est que l'application registerà une déclaration d'objet est plus susceptible d' aggraver le code généré, car elle interfère avec l'allocation de registre du compilateur. Il peut encore y avoir quelques cas où cela est utile (par exemple, si vous savez vraiment à quelle fréquence une variable sera consultée et que vos connaissances sont meilleures que ce qu'un compilateur d'optimisation moderne peut comprendre).

Le principal effet tangible de cela registerest qu'il empêche toute tentative de prendre l'adresse d'un objet. Cela n'est pas particulièrement utile comme indice d'optimisation, car il ne peut être appliqué qu'aux variables locales, et un compilateur d'optimisation peut constater par lui-même que l'adresse d'un tel objet n'est pas prise.


le comportement de ce programme est-il vraiment indéfini selon la norme C? Est-il bien défini en C ++? Je pense que c'est bien défini en C ++.
Destructor

@Destructor: Pourquoi ne serait-il pas défini? Il n'y a pas registerd'objet tableau qualifié, si c'est ce que vous pensez.
Keith Thompson

Oh désolé, j'ai oublié d'écrire le mot-clé de registre dans la déclaration de tableau dans main (). Est-il bien défini en C ++?
Destructor

J'avais tort de définir les registerobjets du tableau; voir le premier point mis à jour dans ma réponse. Il est légal de définir un tel objet, mais vous ne pouvez rien en faire. Si vous ajoutez registerà la définition de sdans votre exemple , le programme est illégal (une violation de contrainte) en C. C ++ ne place pas les mêmes restrictions register, donc le programme serait C ++ valide (mais l'utilisation registerserait inutile).
Keith Thompson

@KeithThompson: le registermot-clé pourrait être utile s'il était légal de prendre l'adresse d'une telle variable, mais uniquement dans les cas où la sémantique ne serait pas affectée en copiant la variable dans un temporaire lorsque son adresse est prise et en la rechargeant à partir du temporaire au point de séquence suivant. Cela permettrait aux compilateurs de supposer que la variable peut être conservée en toute sécurité dans un registre à travers tous les accès de pointeur à condition qu'elle soit vidée à tous les endroits où son adresse est prise.
supercat

9

L'heure du conte!

C, en tant que langage, est une abstraction d'un ordinateur. Il vous permet de faire des choses, en termes de ce que fait un ordinateur, c'est-à-dire manipuler la mémoire, faire des mathématiques, imprimer des choses, etc.

Mais C n'est qu'une abstraction. Et finalement, ce qu'il extrait de vous, c'est le langage d'assemblage. L'assemblage est le langage qu'un CPU lit, et si vous l'utilisez, vous faites les choses en termes de CPU. Que fait un CPU? Fondamentalement, il lit de la mémoire, fait des calculs et écrit dans la mémoire. Le CPU ne fait pas seulement des calculs sur les nombres en mémoire. Tout d'abord, vous devez déplacer un nombre de mémoire en mémoire à l'intérieur du CPU appelé registre. Une fois que vous avez fait tout ce que vous devez faire pour ce numéro, vous pouvez le ramener dans la mémoire système normale. Pourquoi utiliser la mémoire système? Les registres sont limités en nombre. Vous n'obtenez qu'une centaine d'octets dans les processeurs modernes, et les processeurs populaires plus anciens étaient encore plus fantastiquement limités (le 6502 avait 3 registres 8 bits pour votre utilisation gratuite). Ainsi, votre opération mathématique moyenne ressemble à:

load first number from memory
load second number from memory
add the two
store answer into memory

Beaucoup de cela n'est ... pas des mathématiques. Ces opérations de chargement et de stockage peuvent prendre jusqu'à la moitié de votre temps de traitement. C, étant une abstraction d'ordinateurs, a libéré le programmeur du souci d'utiliser et de jongler avec les registres, et puisque le nombre et le type varient selon les ordinateurs, C place la responsabilité de l'allocation des registres uniquement sur le compilateur. À une exception près.

Lorsque vous déclarez une variable register, vous dites au compilateur "Yo, j'ai l'intention que cette variable soit beaucoup utilisée et / ou soit de courte durée. Si j'étais vous, j'essaierais de la garder dans un registre." Lorsque la norme C dit que les compilateurs n'ont rien à faire, c'est parce que la norme C ne sait pas pour quel ordinateur vous compilez, et cela pourrait être comme le 6502 ci-dessus, où les 3 registres sont nécessaires uniquement pour fonctionner , et il n'y a pas de registre de réserve pour conserver votre numéro. Cependant, quand il dit que vous ne pouvez pas prendre l'adresse, c'est parce que les registres n'ont pas d'adresse. Ce sont les mains du processeur. Étant donné que le compilateur n'a pas à vous donner d'adresse, et comme il ne peut jamais avoir d'adresse du tout, plusieurs optimisations sont désormais ouvertes au compilateur. Il pourrait, par exemple, toujours conserver le numéro dans un registre. C'est pas ca' t avoir à se soucier de l'endroit où il est stocké dans la mémoire de l'ordinateur (au-delà de la nécessité de le récupérer à nouveau). Il pourrait même le punter dans une autre variable, le donner à un autre processeur, lui donner un emplacement changeant, etc.

tl; dr: variables de courte durée qui font beaucoup de calculs. N'en déclarez pas trop à la fois.


5

Vous jouez avec l'algorithme sophistiqué de coloration des graphes du compilateur. Ceci est utilisé pour l'attribution des registres. Enfin, surtout. Il agit comme un indice pour le compilateur - c'est vrai. Mais pas ignoré dans son intégralité car vous n'êtes pas autorisé à prendre l'adresse d'une variable de registre (rappelez-vous que le compilateur, à votre merci, essaiera d'agir différemment). Ce qui, d'une certaine manière, vous dit de ne pas l'utiliser.

Le mot-clé a été utilisé depuis très longtemps. Quand il y avait seulement si peu de registres qui pouvaient tous les compter avec votre index.

Mais, comme je l'ai dit, obsolète ne signifie pas que vous ne pouvez pas l'utiliser.


13
Certains des matériels plus anciens avaient plus de registres que les machines Intel modernes. Le nombre de registres n'a rien à voir avec l'âge et tout à voir avec l'architecture du processeur.
JUSTE MON AVIS correct

2
@JUSTMYcorrectOPINION En effet, X86 en a fondamentalement six en tout, laissant au plus 1 ou 2 pour dédicace à «s'inscrire». En fait, étant donné que tant de code a été écrit ou porté sur une machine pauvre en registres, je soupçonne que cela a grandement contribué à ce que le mot clé `` registre '' devienne un placebo - inutile de suggérer des registres lorsqu'il n'y en a pas. Ici, nous sommes 4+ ans plus tard et heureusement, x86_64 est passé à 14, et ARM est maintenant une grande chose.
greggo

4

Juste une petite démo (sans but réel) pour comparaison: lors de la suppression des registermots clés avant chaque variable, ce morceau de code prend 3,41 secondes sur mon i7 (GCC), avec register le même code se termine en 0,7 secondes.

#include <stdio.h>

int main(int argc, char** argv) {

     register int numIterations = 20000;    

     register int i=0;
     unsigned long val=0;

    for (i; i<numIterations+1; i++)
    {
        register int j=0;
        for (j;j<i;j++) 
        {
            val=j+i;
        }
    }
    printf("%d", val);
    return 0;
}

2
Avec gcc 4.8.4 et -O3, je n'ai aucune différence. Sans -O3 et 40000 itérations, j'obtiens peut-être 50 ms de moins sur un temps total de 1,5 s, mais je ne l'ai pas exécuté suffisamment de fois pour savoir si cela était même statistiquement significatif.
zstewart

Il n'y a aucune différence avec CLANG 5.0, la plate-forme est AMD64. (J'ai vérifié la sortie ASM.)
ern0

4

J'ai testé le mot clé register sous QNX 6.5.0 en utilisant le code suivant:

#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>

int main(int argc, char *argv[]) {
    uint64_t cps, cycle1, cycle2, ncycles;
    double sec;
    register int a=0, b = 1, c = 3, i;

    cycle1 = ClockCycles();

    for(i = 0; i < 100000000; i++)
        a = ((a + b + c) * c) / 2;

    cycle2 = ClockCycles();
    ncycles = cycle2 - cycle1;
    printf("%lld cycles elapsed\n", ncycles);

    cps = SYSPAGE_ENTRY(qtime) -> cycles_per_sec;
    printf("This system has %lld cycles per second\n", cps);
    sec = (double)ncycles/cps;
    printf("The cycles in seconds is %f\n", sec);

    return EXIT_SUCCESS;
}

J'ai obtenu les résultats suivants:

-> 807679611 cycles écoulés

-> Ce système a 3300830000 cycles par seconde

-> Les cycles en secondes sont ~ 0.244600

Et maintenant sans vous inscrire:

int a=0, b = 1, c = 3, i;

J'ai eu:

-> 1421694077 cycles écoulés

-> Ce système a 3300830000 cycles par seconde

-> Le nombre de cycles en secondes est ~ 0.430700


2

Register informerait le compilateur que le codeur pensait que cette variable serait suffisamment écrite / lue pour justifier son stockage dans l'un des rares registres disponibles pour une utilisation variable. La lecture / écriture à partir des registres est généralement plus rapide et peut nécessiter un ensemble de codes d'opération plus petit.

De nos jours, cela n'est pas très utile, car la plupart des optimiseurs de compilateurs sont meilleurs que vous pour déterminer si un registre doit être utilisé pour cette variable et pour combien de temps.


2

Au cours des années soixante-dix, au tout début du langage C, le mot-clé register a été introduit afin de permettre au programmeur de donner des conseils au compilateur, lui disant que la variable serait utilisée très souvent, et qu'il devrait être judicieux de conserver sa valeur dans l'un des registres internes du processeur.

De nos jours, les optimiseurs sont beaucoup plus efficaces que les programmeurs pour déterminer les variables qui sont plus susceptibles d'être conservées dans les registres, et l'optimiseur ne prend pas toujours en compte l'indication du programmeur.

Tant de gens recommandent à tort de ne pas utiliser le mot-clé d'enregistrement.

Voyons pourquoi!

Le mot-clé de registre a un effet secondaire associé: vous ne pouvez pas référencer (obtenir l'adresse de) une variable de type de registre.

Les personnes conseillant aux autres de ne pas utiliser les registres prennent à tort cela comme un argument supplémentaire.

Cependant, le simple fait de savoir que vous ne pouvez pas prendre l'adresse d'une variable de registre, permet au compilateur (et à son optimiseur) de savoir que la valeur de cette variable ne peut pas être modifiée indirectement via un pointeur.

Lorsqu'à un certain point du flux d'instructions, une variable de registre a sa valeur affectée dans le registre d'un processeur et que le registre n'a pas été utilisé depuis pour obtenir la valeur d'une autre variable, le compilateur sait qu'il n'a pas besoin de recharger la valeur de la variable dans ce registre. Cela permet d'éviter un accès mémoire coûteux et inutile.

Faites vos propres tests et vous obtiendrez des améliorations de performances significatives dans vos boucles les plus internes.

c_register_side_effect_performance_boost


1

Sur les compilateurs C pris en charge, il essaie d'optimiser le code afin que la valeur de la variable soit conservée dans un registre de processeur réel.


1

Le compilateur Visual C ++ de Microsoft ignore le registermot clé lorsque l'optimisation globale d'allocation de registre (l'indicateur de compilateur / Oe) est activée.

Voir enregistrer un mot-clé sur MSDN.


1

Le mot-clé Register indique au compilateur de stocker la variable particulière dans les registres CPU afin qu'elle puisse être accessible rapidement. Du point de vue d'un programmeur, le mot-clé de registre est utilisé pour les variables qui sont fortement utilisées dans un programme, afin que le compilateur puisse accélérer le code. Bien que cela dépende du compilateur de conserver la variable dans les registres CPU ou la mémoire principale.


0

Register indique au compilateur d'optimiser ce code en stockant cette variable particulière dans des registres puis en mémoire. c'est une demande au compilateur, le compilateur peut ou non considérer cette demande. Vous pouvez utiliser cette fonction au cas où certaines de vos variables sont consultées très fréquemment. Par exemple: une boucle.

Une autre chose est que si vous déclarez une variable comme registre, vous ne pouvez pas obtenir son adresse car elle n'est pas stockée en mémoire. il obtient son allocation dans le registre CPU.


0

sortie asm de gcc 9.3, sans utiliser de drapeaux d'optimisation (tout dans cette réponse fait référence à une compilation standard sans drapeaux d'optimisation):

#include <stdio.h>
int main(void) {
  int i = 3;
  i++;
  printf("%d", i);
  return 0;
}
.LC0:
        .string "%d"
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 3
        add     DWORD PTR [rbp-4], 1
        mov     eax, DWORD PTR [rbp-4]
        mov     esi, eax
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
        mov     eax, 0
        leave 
        ret
#include <stdio.h>
int main(void) {
  register int i = 3;
  i++;
  printf("%d", i);
  return 0;
}
.LC0:
        .string "%d"
main:
        push    rbp
        mov     rbp, rsp
        push    rbx
        sub     rsp, 8
        mov     ebx, 3
        add     ebx, 1
        mov     esi, ebx
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
        add     rsp, 8
        pop     rbx
        pop     rbp
        ret

Cela force ebxà être utilisé pour le calcul, ce qui signifie qu'il doit être poussé vers la pile et restauré à la fin de la fonction car il est sauvegardé. registerproduit plus de lignes de code et 1 écriture en mémoire et 1 lecture en mémoire (bien qu'en réalité, cela aurait pu être optimisé à 0 R / W si le calcul avait été fait en esi, ce qui se passe en utilisant C ++ const register). Le fait de ne pas utiliser registerentraîne 2 écritures et 1 lecture (bien que le stockage pour charger le transfert se produise lors de la lecture). En effet, la valeur doit être présente et mise à jour directement sur la pile afin que la valeur correcte puisse être lue par adresse (pointeur). registern'a pas cette exigence et ne peut pas être pointé. constet registersont fondamentalement l'opposé de volatileet en utilisantvolatileremplacera les optimisations const à la portée du fichier et du bloc et les registeroptimisations à la portée du bloc. const registeret registerproduira des sorties identiques parce que const ne fait rien sur C à l'étendue du bloc, donc seules les registeroptimisations s'appliquent.

Sur clang, registerest ignoré mais des constoptimisations se produisent toujours.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.