2017-05-05 3 views
0

Je sais comment inverser l'ordre des octets (convert big endian to little endian in C [without using provided func]) - dans ce cas, je voudrais utiliser __builtin_bswap64copie octet inversé uint64_t à uint8_t tableau

Je sais aussi comment copier un uint 64 bits à un tableau de caractères - idéalement memcopy. (How do I convert a 64bit integer to a char array and back?)

Mon problème est la combinaison des deux. A la racine du problème, je suis en train de trouver une alternative plus rapide à ce code:

carr[33] = ((some64bitvalue >> 56) & 0xFF) ; 
carr[34] = ((some64bitvalue >> 48) & 0xFF) ; 
carr[35] = ((some64bitvalue >> 40) & 0xFF) ; 
carr[36] = ((some64bitvalue >> 32) & 0xFF) ; 
carr[37] = ((some64bitvalue >> 24) & 0xFF) ; 
carr[38] = ((some64bitvalue >> 16) & 0xFF) ; 
carr[39] = ((some64bitvalue >> 8) & 0xFF) ; 
carr[40] = (some64bitvalue & 0XFF); 

Comme memcopy ne prend pas le résultat de __builtin_bswap64 comme argument source (? Ou est-elle), j'ai essayé ce :

*(uint64_t *)upub+33 = __builtin_bswap64(some64bitvalue); 

mais je me retrouve avec l'erreur : lvalue requis comme opérande gauche d'affectation

y at-il une alternative plus rapide au code original que je suis en train de remplacer du tout?

+0

Quel est le type de 'upub'? Vous violez peut-être des règles strictes d'alias. – user694733

+0

Pourquoi supposez-vous que c'est trop lent? Avez-vous regardé le code d'assemblage? Avez-vous profilé?Concentrez-vous sur l'écriture d'un code portable et lisible en premier lieu (par exemple en l'enveloppant dans une fonction), optimisez uniquement si vous avez un problème de vitesse. – Olaf

+0

J'ai un problème de vitesse et je suis conscient du "problème d'optimisation prématuré". Ne s'applique pas ici. Ma supposition était basée purement sur l'intuition, mais comparée à '* ((uint64_t *) upub + 33) = __builtin_bswap64 (some64bitval);' mon intuition s'est avérée juste. – Perlator

Répondre

3

Ce:

*(uint64_t *)upub+33 = __builtin_bswap64(PplusQ[di][3]); 

parse comme

(*(uint64_t *) upub) + 33 = __builtin_bswap64(PplusQ[di][3]); 

de sorte que le côté gauche est un uint64_t, pas une lvalue.

Alors, cela fonctionnerait-il?

*(uint64_t *) (upub+33) = __builtin_bswap64(PplusQ[di][3]); 

ou avez-vous dire de jeter upub-uint64_t * d'abord, comme Aconcagua a commenté?

*((uint64_t *) upub + 33) = __builtin_bswap64(PplusQ[di][3]); 

Je ne voyais pas le genre de upub mentionné, donc je ne peux pas dire.

Aussi, j'ai le sentiment qu'il peut y avoir un problème avec le aliasing rules si upub pointe vers l'origine à un autre type, de sorte que vous pouvez utiliser quelque chose comme de -fno-strict-aliasing gcc ou effectuer la cession par un syndicat ou un octet à une heure comme dans votre premier extrait de code.

+0

Qu'est-ce que 'upub'? Selon comment est déclaré/mis en place, cela peut et va invoquer UB. – Olaf

+0

@Olaf, nous ne savons pas, la question ne dit pas. Je pensais que j'ai mentionné que l'information est manquante, et je pensais également que j'ai mentionné le problème d'aliasing possible? Je serais heureux de voir une vérification sur le sujet d'une manière ou d'une autre. – ilkkachu

+0

upub/carr est ** comme le titre le dit ** un tableau 'uchar' /' uint8_t'. '* (uint64_t *) (upub + 33) = __builtin_bswap64 (PplusQ [di] [3]);' fonctionne parfaitement avec tous les avertissements, pédales et autres sifflets activés. C'est aussi plus rapide que le code original. – Perlator

1

Vous pouvez copier comme:

uint64_t tmp = __builtin_bswap64(some64bitvalue); 
memcpy(upub+33,&tmp,sizeof(tmp)); 

en supposant upub est variable pointeur

+0

Fonctionne, mais est plus lent que le code d'origine. – Perlator

1

Lors de l'écriture du code endian indépendant il n'y a pas d'alternative à des changements de bits. Votre code est probablement déjà proche de l'idéal.

Ce que vous pouvez jouer avec est d'utiliser une boucle au lieu de chiffres codés en dur. Quelque chose le long des lignes de celle-ci:

for(uint_fast8_t i=0; i<8; i++) 
{ 
    carr[i+offset] = (some64bitvalue >> (56-(i*8)) & 0xFF; 
} 

Cela peut tourner plus ou moins vite ou égale par rapport à ce que vous avez déjà, en fonction du système. Dans l'ensemble, il n'y a aucun sens à discuter de l'optimisation manuelle comme celle-ci sans un système spécifique à l'esprit.