那么对于(char*)&big,指针转换后解释为char类型怎么办?
如果 char 是 8 位,这是大多数现代 C 实现中的情况,那么 uint32_t big 中有四个字节,您可以对从 (char *) &big + 0 到 @987654326 的地址进行算术运算@。您还可以读取和写入从(char *) &big + 0 到(char *) &big + 3 的字节,这些字节将访问big 表示中的各个字节。虽然算术被定义为在(char *) &big + 4 下工作,但这只是一个端点。那里没有定义的字节,您不应该使用该地址来读取或写入任何内容。
- 将
(char*)&big 的地址转移 到(char*&big)+1、(char*&big)+2 等是否是未定义的行为?
这些是加法,而不是移位,语法是(char *) &big + 1,而不是(char*&big)+1。算术是为从 +0 到 +4 的偏移量定义的。
- 对于 shift 和 edit
(char*)&big+1987654336@,这是一种未定义的行为吗?
允许使用指向char 的指针读取和写入big 中的字节。这是字符类型的特殊规则。通常,不应使用不相关的类型访问对象的字节。例如,无法使用 int 类型访问 float 对象。但是,字符类型是特殊的;您可以使用字符类型访问任何对象的字节。
但是,最好使用unsigned char,因为它可以避免有符号值的复杂性。
- 我见过这样的代码。
允许使用memcpy 读取或写入对象的字节。 memcpy 被定义为像复制字符一样工作。
请注意,虽然访问对象的字节是由 C 标准定义的,但字节表示值的方式部分是由实现定义的。不同的 C 实现可能对对象中的字节使用不同的顺序,并且可能存在其他差异。
顺便说一句,我想问一个分叉的问题,为什么在这个例子中第一个printf 给出ffffffff?不应该是ff吗?
在您的 C 实现中,char 是有符号的,可以表示从 -128 到 +127 的值。在 *((char*)&big + 1) = 0xff; 中,0xff 是 255,太大而无法放入 char。它以实现定义的方式转换为char 值。您的 C 实现将其转换为 -1。 (-1 的 8 位二进制补码表示,即 11111111 位,使用与 255 的二进制表示相同的位,同样是 11111111 位。)
然后printf("%02x\n\n\n", *((char*)&big+1)); 将此值-1 传递给printf。由于它是char,因此将其提升为int 以传递给printf。这会产生相同的值 -1,但它有 32 位,11111111111111111111111111111111。然后你传递一个int,但printf 期望unsigned int 对应%02x。这种行为不是由 C 标准定义的,但是您的 C 实现读取 32 位,就好像它们是 unsigned int。作为unsigned int,32 位 1111111111111111111111111111111 代表值 4,294,967,295 或 0xffffffff,这就是 printf 打印的内容。
您可以使用printf("%02hhx\n\n\n", * ((unsigned char *) &big + 1)); 打印正确的值。作为 unsigned char,位 11111111 代表 255 或 0xff,并将其转换为 int 会产生 255 或 0x000000ff。