簡體   English   中英

在C / C ++中向指針添加1個字節的正確方法是什么?

[英]What's the correct way to add 1 byte to a pointer in C/C++?

我現在用這個代碼將指針移動1個字節,但我感​​覺不清楚......

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

char是1個字節,但沒有為字節操作目的定義。 我相信還有另一種方法來執行此字節操作。 字節操作的正確方法是什么?

PS。 我將示例代碼修改為有效。 它現在用Clang編譯為C ++。

在C99中,你有stdint.h頭文件,它包含int8_tuint8_t類型,它們保證是8位(通常只是char的typedef)。 除此之外,C或C ++中的字節沒有真正的語言級別支持,事實上標准就是說sizeof例如以char (而不是字節)為單位。 還有CHAR_BIT宏告訴你一個字節中的位數,在某些平台上char例如是9位。 當然我用字節假設你的意思是八位字節。

我覺得你很困惑:

char是1個字節,但沒有為字節操作目的定義。 我相信還有另一種方法來執行此字節操作。 字節操作的正確方法是什么?

究竟是什么byte意味着什么,如果不是char意味着完全相同的東西?

在C和C ++中,字符字節。 根據定義 不是這種情況是字節必然是八位字節 一個字節至少包含8位。 誰也不能保證一個給定的平台甚至能夠引用的內存塊,這正是 8位。

((char*)a)++

這是邪惡的Microsoft擴展之一。 指針轉換表達式是一個rvalue,但根據C ++語言規則,increment運算符僅適用於左值。 g ++拒絕編譯它。

你不應該這樣做。 許多架構都有數據對齊要求。 例如,取消引用未與SPARC機器上的字邊界對齊的指針將使程序崩潰,並出現總線錯誤( SIGBUS )。


int拆分為字節的可移植方法是使用按位運算(假設為8位字節):

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);

同樣可以是非便攜地與實現型雙關通過招數union S,如:

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;

但是,此技術會導致實現定義的行為,因此不建議

  • 字節順序取決於主機系統的字節順序。
  • 位字段的打包不可移植。
  • 由於編譯器生成的代碼而增加了復雜性/開銷,以防止未對齊的訪問。
  • 對齊問題,關於不阻止它們的實現。
((char*&)a)++;

要么:

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

我希望你確切知道你在做什么。 首先,你的結果是 - 根據定義 - 未對齊的int指針。 根據架構和操作系統,這可能會有問題。

plz,使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM