C语言 Endianness &将字符存储到无符号整数中

0ejtzxu1  于 2023-05-28  发布在  其他
关注(0)|答案(2)|浏览(114)

我正在ext2 inode中初始化一个符号链接(学校作业)。
我的想法是用十六进制来做,因为字段被定义为uint32_t i_block[EXT2_N_BLOCKS]
例如:

#include <stdio.h>

int main () {
  // unsigned int is 32 bytes on my system
  unsigned int i = 0x68656c6c; // hell
  printf("%.*s\n", 4, &i");

我拿到输出了

lleh

这是因为我的系统是little-endian吗?这是否意味着如果我硬编码相反的顺序,它就不会移植到big-endian系统(我的最终目标是hello-world)?
将字符串存储到无符号整数数组中的最好、最简单的方法是什么?

ndh0cuux

ndh0cuux1#

这是因为我的系统是little-endian吗?
是的
这是否意味着如果我硬编码相反的顺序,它将不会端口到big-endian系统
依赖于整数字节顺序的代码实际上是不可移植的。
将字符串存储到无符号整数数组中的最好、最简单的方法是什么?
最好的方法是根本不使用整数,而使用char,它与整数不同,不依赖于字节序,实际上是为了存储字符而设计的。
你可以忽略它是一个整数类型,只是memcpy一个字符串到它:

unsigned int i;
memcpy(&i, "hell", 4);

或者,如果您喜欢:memcpy(&i, "\x68\x65\x6c\x6c", 4);
否则,你将不得不发明一些丑陋的黑客,例如:

#define LITTLE_ENDIAN  (*(unsigned char*) &(int){0xAA} == 0xAA)
unsigned int i = LITTLE_ENDIAN ? 0x6c6c6568 : 0x68656c6c;
xqkwcwgp

xqkwcwgp2#

严格来说,printf("%.*s\n", 4, &i");undefined behavior(UB),因为"%.s"需要一个指向字符的指针,而&i是一个指向int的指针。
更好的替代方案是使用union

union {
  unsigned u;
  unsigned char uc[sizeof (unsigned)];
} x = { .u = 0x68656c6c};

printf("%.*s\n", (int) sizeof x.uc, x.uc);

使用uint32_t而不是unsigned更好。
将字符串存储到无符号整数数组中的最好、最简单的方法是什么?
通过union避免所有的字节序问题,并通过.uc成员进行初始化。

#include <stdio.h>
#define N 42

int main(void) {
  union {
    unsigned u[N];
    unsigned char uc[sizeof (unsigned[N])];
  } x = { .uc = "Hello"};
  printf("<%.*s>\n", (int) sizeof x.uc, x.uc);
}

输出量

<Hello>

请注意,.uc[]可能不是具有足够长的初始化器的 string,因为它可能缺少 *null字符 *。

相关问题