0
votes

Erreur du compilateur lors de la coulée UINT64_T à la structure

Je reçois l'erreur suivante:

os: Linux 5.7.9-arch1-1 x86_64
compiler: g++ (GCC) 10.1.0


9 commentaires

Il semble parce qu'il n'y a pas de fonction correspondante.


Pourquoi ne pas définir le constructeur prise uint64_t ?


Je ne sais pas à quoi ressemble votre moulage, mais il semble que le compilateur pense que vous essayez d'appeler AB . Le transmettez-lui votre uint64_t


Notez que alignof (uint64_t) peut être 8, tandis que alignof (AB) peut être 4. Vous devez mieux utiliser memcpy ici.


Que veux-tu accomplir? Décomposer n to m + k * 2 ^ 32 ?


Vous auriez besoin de faire une magie du pointeur pour permettre un tel casting, mais ne faites pas cela s'il vous plaît. Il suffit d'écrire un constructeur de conversion.


Je ne veux pas appeler une fonction à chaque fois que je souhaite copier des données. Je ne veux qu'une seule instruction MOV après le démontage dans cet endroit.


S'il vous plaît, donnez-nous le code causé l'erreur.


Ce que vous essayez vous apparaît comme genre de type-punning (généralement fait avec Union s) . Cependant, cela est interdit en C ++. Le moyen sûr est d'utiliser des opérateurs de bits ou memcpy () (comme déjà recommandé).


3 Réponses :


1
votes

Pourquoi ne puis-je pas lancer uint64_t à AB? P>

parce que uint64_t code> n'est pas convertible (même explicitement) à AB code>. p>

si vous voulez A code> pour contenir le octets dans les adresses de mémoire inférieure et B code> pour contenir les octets dans des adresses de mémoire supérieures 1 sup>, alors vous pouvez faire: p>

ab a = std::bit_cast<ab>(some_uint64_t);


1 commentaires

Il convient de souligner que le bit_cast peut être effectué à l'intérieur du AB :: AB (uint64_t) constructeur de telle sorte que les conversions soient plus faciles et uniformes à l'extérieur de la structure.



3
votes

comme une note latérale, vous pouvez peut-être sauter le AB CODE> STRUTER et bit votre chemin avec deux uint32_t code> emballé à l'intérieur d'un uint64_t code> . Voici un exemple simple:

#include <stdint.h>
#include <stdio.h>
int main(int argc, char **argv)
{
    uint64_t v = 0xbadf00ddeadbeef;
    printf("value is 0x");
    printf("%x"  ,(uint32_t)  (v & 0x00000000FFFFFFFF));
    printf("%x\n",(uint32_t) ((v & 0xFFFFFFFF00000000)>>32));
    return 0;
}


6 commentaires

@erorika j'ai supprimé le AB struct et maintenant il est valide


((V & 0XFFFFFFFFFF00000000) >> 32)) peut être écrit plus simplement comme (v >> 32) . Les bits bas tombent tout simplement disparu. +1.


@Petebecker Néanmoins, la symétrie / motif aide à la lisibilité. Pourrait même ajouter >> 0 à la ligne précédente.


@erorika - Je trouve les trucs superflus distrayants. Je sais ce que >> 32 fait. Je ne sais pas quoi compter f s pour voir qu'ils ne font rien.


@Petebecker peut être utile de noter que le masque est également redondant sur la première expression puisque les hauts morceaux disparaissent également; dans le casting.


@erorika - True, les hauts bits tombent aussi. Mais c'est à cause de la distribution; Ce n'est pas une propriété de l'expression intérieure elle-même. Je préfère généralement avoir des moulages aussi que possible, car ils ont tendance à cacher leurs détails.



1
votes

Vous ne pouvez pas attribuer de type intégré à une structure sans dire C ++ ce que cela signifie. Alors, comment faites-vous cela?

-> Faites confiance à votre compilateur. h1 >

Si vous définissez correctement votre constructeur: P>

test(unsigned long):
        mov     rax, rdi
        ret


5 commentaires

Notez que cette mise en œuvre se comporte différemment d'une attente de réinterprétation / memcpy. Cela copie les octets les moins importants à A plutôt que les octets dans les adresses de mémoire inférieure. Sur les petites systèmes d'Endian, cela signifie aucun changement dans l'ordre, mais sur les grands systèmes Endian, cela signifie que la commande sera échangée. Cela peut être souhaitable tant que c'est l'intention.


@erorika Vous êtes absolument correct. Je dirais que cela le rend portable, tandis que REINTERPRET / MEMCY vous donne une machine dépendante de la machine quelque chose .


En effet. Mon point est simplement qu'il est subtilement différent de ce que OP semble essayer de faire. Il est certainement possible que c'est ce que l'OP aurait dû essayer de faire.


@erorika en pensant à ce sujet, on pourrait probablement ajouter des chèques de compilation pour inverser l'ordre sur les machines de Big-Endian, de sorte qu'il imite plus de près MEMCY.


À mon avis, il est préférable d'éviter ceux-ci. Utilisez MEMCY / BIT_CAST / REINTERPRET (en tant que caractères non signés) si vous voulez l'ordre d'octet; Utilisez Maj enfoncé si vous voulez de l'ordre d'importance (et une communication portable). Pas besoin de chèques de compilation pour la compilation non plus.