繁体   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