将short int复制到char数组中

5

我有一个短整型变量叫做s_int,它的值为2。

unsighed short s_int = 2;

我想将这个数字复制到一个字符数组的第一和第二个位置。

假设我们有一个char buffer[10];。我们要将s_int的两个字节复制到buffer[0]buffer[1]

我该怎么做?

5个回答

16

通常处理这个问题的方法是使用位运算符,逐字节地对其进行切片和操作:

b[0] = si & 0xff;
b[1] = (si >> 8) & 0xff;
虽然这应该真正地完成为一个unsigned char,而不是一个普通的char,因为它们在大多数系统上是有符号的。
存储较大的整数可以用类似的方式或循环来完成。

& 0xff 的原因是什么? - Almir
它将隐式截断转化为显式截断。换言之,程序员的意图变得清晰明了。(我认为有些编译器可能会抱怨这个?) - crazyscot
哦,我明白了 :) 谢谢 - Almir
我该如何从b[0]b[1]重构int类型的数据? - Casey

7

*((short*)buffer) = s_int;

但请注意,最终的字节顺序会因大小端而异。


不行,考虑一下对齐。如果缓冲区指向内存中的奇数索引 - 假设地址为0xFFF01,那你就大麻烦了。 - INS
@Iulian:我没有听说过x86上有这种限制,但当然它对其他一些架构是基本的。 - crazyscot
@Iulian: 这不是在X86上的问题(或许只有速度上的问题...)。然而,在其他平台上,如IA64、MIPS、可能还有ARM等,这非常重要。 - botismarius
@crazyscot 和 @botismarius,我同意你们的评论,但我们正在讨论 C 语言;我们应该尽可能地保持可移植性。 - INS
1
John Ledbetter:该代码没有使用强制类型转换表达式作为左值;它使用一元运算符 * 的结果作为左值,这是可以的(因为它确实是一个左值)。然而,它仍然存在对齐问题。 (“将强制类型转换用作左值”是像 (int)x = 10; 这样的表达式) - caf
显示剩余2条评论

3
通过使用指针和强制类型转换。
unsigned short s_int = 2;
unsigned char buffer[sizeof(unsigned short)];

// 1.
unsigned char * p_int = (unsigned char *)&s_int;
buffer[0] = p_int[0];
buffer[1] = p_int[1];

// 2.
memcpy(buffer, (unsigned char *)&s_int, sizeof(unsigned short));

// 3.
std::copy((unsigned char *)&s_int,
          ((unsigned char *)&s_int) + sizeof(unsigned short),
          buffer);

// 4.
unsigned short * p_buffer = (unsigned short *)(buffer); // May have alignment issues
*p_buffer = s_int;

// 5.
union Not_To_Use
{
  unsigned short s_int;
  unsigned char  buffer[2];
};

union Not_To_Use converter;
converter.s_int = s_int;
buffer[0] = converter.buffer[0];
buffer[1] = converter.buffer[1];

3

我会使用memcpy函数进行复制,代码如下:

memcpy(buffer, &s_int, 2);

这样可以正确地保留字节序,因此如果您将buffer强制转换为unsigned short *,您可以正确地读取s_int的相同值。其他解决方案必须具有端对端感知,或者您可以交换最低有效位和最高有效位。当然,sizeof(short)必须为2。


1
memcpy()是一个不错的方法,但请注意,“保留字节序”并不总是正确的。crazyscot的答案将答案放入了具有已知字节序的缓冲区中,这通常是真正需要的(例如,如果要将缓冲区保存到文件或通过网络发送)。您的答案将答案放入具有主机字节序的缓冲区中,这也是有时需要的(但不太常见)。 - caf
当然可以:我所说的“保留字节顺序”是指数据被存储到缓冲区中的方式与短整型在内存中保存的方式相同,允许用户直接从缓冲区访问短整型值,前提是用户不需要将字节顺序更改为特定的顺序。 - ShinTakezou
请注意,仅当缓冲区正确对齐以进行此类访问时,才可以直接从缓冲区访问 short。通常情况下,如果您要将其直接访问为 short,则应将其声明为包含 short 成员的“struct”,而不是 char 数组。 - caf
在需要对齐的处理器上,对于需要2字节对齐的处理器,缓冲区也会被对齐,因此可以安全地访问它;据我所知,x86不需要这样做(可能,对非对齐内存的访问只会变慢)。 - ShinTakezou

0

如果你不想做那些位运算的事情,你可以这样做

char* where = (char*)malloc(10);
short int a = 25232;
where[0] = *((char*)(&a) + 0);
where[1] = *((char*)(&a) + 1);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接