首页 > 解决方案 > 将字符串文字复制到 uint32_t 数组并访问它

问题描述

我在其他地方粘贴了下面的代码,但建议它是一个不好的解决方案。该标准对 memcpy 有这样的说法:

“memcpy 函数将 n 个字符从 s2 指向的对象复制到 s1 指向的对象中。如果复制发生在重叠的对象之间,则行为未定义。”

关于uint32_t:

“typedef 名称 uintN_t 指定一个宽度为 N 且没有填充位的无符号整数类型。因此,uint24_t 表示这种宽度正好为 24 位的无符号整数类型。”

有没有对齐问题?我一直在 linux 上使用它,从未遇到任何错误等。当我不得不担心字节顺序时,我只使用按位操作进行访问,例如通过来自另一个架构的链接接收数据。请投一些光。

#include <stdio.h>
 #include<string.h>
 #include<stdint.h>
 char* pointer = "HelloWorld!Hell!";
 uint32_t arr[4];
 unsigned char myArray[16];
 int main(void) {
     memcpy(arr, pointer, (size_t)16);

     // Is this illegal ? 
     char *arr1 = (char *)arr;

     for(int i = 0 ; i < 16; i++)
     {
         printf("arr[%d]=%c\n", i, arr1[i]);
     }
 }

标签: cpointersprintf

解决方案


调用memcpy很好。您有未定义行为的地方在这里:

printf("%s\n", arr);

%s格式说明符需要一个参数,char *但您传递的是uint32_t *. 这种参数不匹配是未定义的行为。这两种指针类型在您的系统上可能具有相同的表示形式,但通常不一定如此。

即使类型匹配,您仍然会拥有 UB,因为arr它不够大,无法包含 string "HelloWorld!Hell!"。此字符串(包括空终止字节)为 17 个字节宽,因此不复制空终止符。然后printf读取数组末尾的 UB。

例如,我将变量列表修改如下:

 uint32_t x = 0x11223344;
 uint32_t arr[4] = { 1, 2, 3, 4 };
 uint32_t y = 0x55667788;

并得到以下输出:

HelloWorld!Hell!�wfU

至于这个:

char *arr1 = (char *)arr;

这是合法的,因为一种对象类型的指针可以转换为指向另一种对象类型的指针。此外,由于目标类型是char *,取消引用该指针以访问原始对象的底层字节是合法的。


推荐阅读