Quelle est la bonne façon d’append 1 octet à un pointeur en C / C ++?

J’utilise ce code pour déplacer le pointeur d’1 octet à présent, mais je sens quelque chose d’incertain.

int* a = (int*)malloc(sizeof(int)); void* b = ((char*)a)+1; 

char est de 1 octet, mais n’est pas défini pour les besoins de l’opération d’octet. Je crois qu’il y a une autre manière de faire cette opération d’ octet . Quelle est la bonne façon de passer en mode octet ?

PS J’ai modifié le code de l’échantillon pour qu’il soit valide. Il est maintenant compilé en C ++ avec Clang.

Je pense que tu es confus:

char est de 1 octet, mais n’est pas défini pour les besoins de l’opération d’octet. Je crois qu’il y a une autre manière de faire cette opération d’ octet . Quelle est la bonne façon de passer en mode octet ?

Qu’attendez-vous exactement par byte , si ce n’est exactement la même chose que char ?

En C et en C ++, les caractères sont des octets. Par définition Ce qui n’est pas le cas, c’est que les octets sont nécessairement des octets . Un octet contient au moins 8 bits. Il n’y a aucune garantie qu’une plateforme donnée permette même de référencer un bloc de mémoire qui fait exactement 8 bits.

En C99, vous avez l’en-tête stdint.h , qui contient les types int8_t et uint8_t , garantis être de 8 bits (et qui ne sont généralement que des typedefs pour char). Au-delà de cela, il n’existe pas de véritable niveau de langage pour les octets en C ou C ++. En fait, la norme s’efforce de dire que sizeof par exemple, est sizeof en unités de caractère (et non en octets). Il y a aussi la macro CHAR_BIT qui vous indique le nombre de bits dans un octet. Sur certaines plates-formes, par exemple, le caractère était de 9 bits. Bien sûr, je suppose par octet que vous voulez dire octet.

((char*)a)++

C’est l’une de ces mauvaises extensions Microsoft. Une expression de conversion de pointeur est une valeur rvalue, mais selon les règles du langage C ++, l’opérateur d’incrémentation ne fonctionne que sur les valeurs lvalues. g ++ refuse de comstackr cela.

Tu ne devrais pas faire ça. De nombreuses architectures ont des exigences d’alignement des données. Par exemple, le déréférencement d’un pointeur qui n’est pas aligné sur une limite de mot sur une machine SPARC SIGBUS le blocage du programme avec une erreur de bus ( SIGBUS ).


Le moyen portable de diviser votre int en octets est d’utiliser des opérations au niveau du bit (en supposant des octets de 8 bits):

 uint8_t b3 = 0x12, b2 = 0x34, b1 = 0x56, b0 = 0x78; uint32_t a; a = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; printf("%08X\r\n", a); a = 0x89ABCDEF; b3 = (a >> 24) & 0xFF; b2 = (a >> 16) & 0xFF; b1 = (a >> 8) & 0xFF; b0 = a & 0xFF; printf("%02X%02X%02X%02X\r\n", b3, b2, b1, b0); 

La même chose peut être réalisée de manière non portable avec des astuces de frappe de type via des union , telles que:

 typedef union { uint32_t val; uint8_t bytes[4]; } DWORD_A; typedef union { uint32_t val; struct { unsigned b0:8; unsigned b1:8; unsigned b2:8; unsigned b3:8; }; } DWORD_B; 

Cependant, cette technique conduit à un comportement défini par l’implémentation et n’est donc pas recommandée :

  • L’ordre des octets dépend de l’endianité du système hôte.
  • L’emballage des champs de bits n’est pas portable.
  • Complexité / surcharge supplémentaire due au code généré par le compilateur pour éviter un access mal aligné.
  • Problèmes d’alignement sur les implémentations qui ne les empêchent pas.
 ((char*&)a)++; 

Ou:

 a = (int*)((char*)a+1); 

J’espère que vous savez exactement ce que vous faites. D’une part, vous vous retrouvez avec, par définition, un pointeur int non aligné. Selon l’architecture et le système d’exploitation, cela peut poser problème.

plz, utilisez void *

 int g = 10; int *a = &g; printf("a : %p\n",a); printf("a : %p\n", ++a); printf("a : %p\n", (void*)((char*)a+1)); 

a: 0xbfae35dc a: 0xbfae35e0 a: 0xbfae35e1