如何在c中的char数组中复制uint8_t数组
How to copy uint8_t array in char array in c
我会在 char 数组中复制一个 uint8_t 数组。
我尝试了不同的解决方案:cast、memcopy、strcpy ...
但它不起作用!我的小例子是:
uint32_t num = 123456789;
printf("\n num: %"PRIu32 "\n", num);
uint32_t x;
uint8_t a[4];
char b[4];
num=htonl(num);
a[0]=num;
a[1]=num>>8;
a[2]=num>>16;
a[3]=num>>24;
b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
b[3] = a[3];
printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]);
printf("\nB: %x %x %x %x", b[0],b[1],b[2],b[3]);
x= b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
x=ntohl(x);
printf("\n x vale: %"PRIu32 "\n", x);
}
印刷品是:
num: 123456789
A: 7 5b cd 15
B: 7 5b ffffffcd 15
x: 123457023
为什么我在 x 中得到不同的数字?
您必须稍微修改您的代码以确保处理一些未定义的行为,例如 signed int
值溢出。
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <arpa/inet.h>
int main()
{
uint32_t num = 123456789;
printf("\n num: %" PRIu32 "\n", num);
uint32_t x;
uint8_t a[4];
unsigned char b[4];
num=htonl(num);
a[0] = num & 0x000000FFu;
a[1] = (num & 0x0000FF00u) >> 8;
a[2] = (num & 0x00FF0000u) >>16;
a[3] = (num & 0xFF000000u) >>24;
b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
b[3] = a[3];
printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]);
printf("\nB: %x %x %x %x", b[0], b[1], b[2], b[3]);
x = b[0] | (b[1] & 0x000000FFu)<<8 | (b[2] & 0x000000FFu)<<16 | (b[3] & 0x000000FFu)<<24;
x = ntohl(x);
printf("\n x vale: %" PRIu32 "\n", x);
return 0;
}
如您所见:
b
数组声明为unsigned char
以避免undefined behavior。它还可以更正代码中第 3 个 printf
打印的值。
- 将值插入
a
数组,如果您在将要移动的位移动到正确位置之前屏蔽它们,会更清楚。
- 当您计算
x
值时,您正在对 8 bit
变量执行左移。所以你在 8 班后失去了所有位。用 32 bit HEX literal
对它们进行 &ing 你可以确保使用正确的位移位大小和 or
s
关于第 3 点,正如 @2501 指出的那样,您必须使用 u 作为文字,以确保在 int
的大小小于 32 bts 或 signed int 具有陷阱值的平台上避免 UB。见 6.4.4.1。标准的 p5。
我不明白为什么对 memcpy
的调用不起作用。只需检查 CHAR_BIT == 8
以确保 char
被定义为 8 位类型(一些实现将 char
定义为 16 位大),然后调用 memcpy(b, a, sizeof(b) / sizeof(b[0]))
。这应该是诀窍。
不要忘记为 memcpy
添加 string.h
,为 CHAR_BIT
添加 limits.h
。
正如其他人指出的那样,您仍然可能会遇到麻烦,因为 char
的签名也是实现定义的。因此,您应该将 b
声明为 unsigned char
以防止未定义的行为。
要 100% 保存,您还应该检查 a
和 b
是否具有相同的大小,这样您就不会出现任何运行时错误。
我会在 char 数组中复制一个 uint8_t 数组。 我尝试了不同的解决方案:cast、memcopy、strcpy ... 但它不起作用!我的小例子是:
uint32_t num = 123456789;
printf("\n num: %"PRIu32 "\n", num);
uint32_t x;
uint8_t a[4];
char b[4];
num=htonl(num);
a[0]=num;
a[1]=num>>8;
a[2]=num>>16;
a[3]=num>>24;
b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
b[3] = a[3];
printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]);
printf("\nB: %x %x %x %x", b[0],b[1],b[2],b[3]);
x= b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
x=ntohl(x);
printf("\n x vale: %"PRIu32 "\n", x);
}
印刷品是:
num: 123456789
A: 7 5b cd 15
B: 7 5b ffffffcd 15
x: 123457023
为什么我在 x 中得到不同的数字?
您必须稍微修改您的代码以确保处理一些未定义的行为,例如 signed int
值溢出。
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <arpa/inet.h>
int main()
{
uint32_t num = 123456789;
printf("\n num: %" PRIu32 "\n", num);
uint32_t x;
uint8_t a[4];
unsigned char b[4];
num=htonl(num);
a[0] = num & 0x000000FFu;
a[1] = (num & 0x0000FF00u) >> 8;
a[2] = (num & 0x00FF0000u) >>16;
a[3] = (num & 0xFF000000u) >>24;
b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
b[3] = a[3];
printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]);
printf("\nB: %x %x %x %x", b[0], b[1], b[2], b[3]);
x = b[0] | (b[1] & 0x000000FFu)<<8 | (b[2] & 0x000000FFu)<<16 | (b[3] & 0x000000FFu)<<24;
x = ntohl(x);
printf("\n x vale: %" PRIu32 "\n", x);
return 0;
}
如您所见:
b
数组声明为unsigned char
以避免undefined behavior。它还可以更正代码中第 3 个printf
打印的值。- 将值插入
a
数组,如果您在将要移动的位移动到正确位置之前屏蔽它们,会更清楚。 - 当您计算
x
值时,您正在对8 bit
变量执行左移。所以你在 8 班后失去了所有位。用32 bit HEX literal
对它们进行 &ing 你可以确保使用正确的位移位大小和or
s
关于第 3 点,正如 @2501 指出的那样,您必须使用 u 作为文字,以确保在 int
的大小小于 32 bts 或 signed int 具有陷阱值的平台上避免 UB。见 6.4.4.1。标准的 p5。
我不明白为什么对 memcpy
的调用不起作用。只需检查 CHAR_BIT == 8
以确保 char
被定义为 8 位类型(一些实现将 char
定义为 16 位大),然后调用 memcpy(b, a, sizeof(b) / sizeof(b[0]))
。这应该是诀窍。
不要忘记为 memcpy
添加 string.h
,为 CHAR_BIT
添加 limits.h
。
正如其他人指出的那样,您仍然可能会遇到麻烦,因为 char
的签名也是实现定义的。因此,您应该将 b
声明为 unsigned char
以防止未定义的行为。
要 100% 保存,您还应该检查 a
和 b
是否具有相同的大小,这样您就不会出现任何运行时错误。