2017-05-24 7 views
1
u8 num[] = {0x00, 0x00, 0x40}; 

u8*ptr = num; 

u8 tag; 

u16 len; 

tag = *ptr++; 

len = (u16)*ptr++ <<8 | *ptr++; 

Je me attends len = 0x0040 mais len est setted avec 0x0000 en studio visuel 2013. Je ne sais pas pourquoi cela est survenu. Comment expliquer le point de vue de la priorité des opérateurs?en C, *, =, ++, << | opérateur

+2

Ajoutez des parenthèses et vous n'aurez pas besoin de compter sur la priorité des opérateurs. Problème résolu. (bien qu'il puisse y avoir un comportement indéfini aveC++) – byxor

+2

La réponse est simple: N'écrivez pas de code comme ça. Écrivez-le avec des parenthèses, ou des lignes séparées, puis laissez le compilateur l'optimiser. –

+0

Copie possible de [Pourquoi ces constructions (utilisant ++) undefined behavior?] (Https://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior) –

Répondre

1

En ce qui concerne la priorité d'opérateur, je vous suggère d'abord jeter un oeil à ce table.

Maintenant, le ++/-- peut être difficile parce que les opérateurs dont vous avez besoin pour déterminer s'ils sont des opérateurs de préfixe ou postfix, comme vous pouvez le voir dans le tableau si elles étaient les préfixes ils auraient la même priorité que * (déréférencement) .

Donc, nous allons analiZe ce qui se passe avec votre dernière ligne len = (u16)*ptr++ <<8 | *ptr++;, il y a cet ensemble d'opérateurs {=, (cast), *(dereference), ++(postfix), <<, |}, de sorte que l'ordre d'évaluation selon cette table serait ++(postfix), *dereference, (type), <<, |, =

Ce serait en ce qui concerne l'ordre d'évaluation , mais vous devez considérer:

Postfix incrément/décrément ont une grande priorité, mais l'augmentation réelle ou décrément de l'opérande est retardée (pour être accompli quelque temps avant la déclaration complète execut ion).

Cela dit, voici quelques façons d'obtenir ce que vous voulez:

ptr[1]<<8 | ptr[2] 

ou:

*(ptr+1) <<8 | *(ptr+2) 

Un dernier conseil, soyez prudent lorsque vous traitez avec des opérateurs la même précédence, comme vous pouvez le voir dans le tableau, l'associativité peut être de gauche à droite ou de droite à gauche.

PS: Bien sûr, le code asm généré dépendra par le compilateur & config utilisé, voici un exemple de vs2015 en mode débogage de cette ligne:

; 7 :  u16 len = (u16)*ptr++ <<8 | *ptr++; 

    mov ecx, DWORD PTR _ptr$[ebp] 
    movzx edx, BYTE PTR [ecx] 
    shl edx, 8 
    mov eax, DWORD PTR _ptr$[ebp] 
    movzx ecx, BYTE PTR [eax] 
    or edx, ecx 
    mov WORD PTR _len$[ebp], dx 
    mov edx, DWORD PTR _ptr$[ebp] 
    add edx, 1 
    mov DWORD PTR _ptr$[ebp], edx 
    mov eax, DWORD PTR _ptr$[ebp] 
    add eax, 1 
    mov DWORD PTR _ptr$[ebp], eax 

Bonne codage.

+0

L'effet de côté de «++» n'est pas ordonné, et un opérande peut être évalué plus tôt que vous ne le faites dans votre liste –

+0

@MM Op dit qu'il utilise Visual Studio 2013, j'ai testé et j'ai référé à ce compilateur, pourriez-vous s'il vous plaît élaborer ce que vous voulez dire? – BPL

+1

Il n'existe pas la commande que vous revendiquez (en C++ standard). Le comportement que vous observez sur une exécution particulière de vC++ peut ou non être répliqué sur d'autres exécutions, même avec le même compilateur. –