【问题标题】:Copying a string literal to an uint32_t array and accessing it将字符串文字复制到 uint32_t 数组并访问它
【发布时间】:2020-06-20 18:54:33
【问题描述】:

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

"memcpy 函数将 s2 指向的对象中的 n 个字符复制到 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]);
     }
 }

【问题讨论】:

  • 嗯,问题是 sizeof("HelloWorld!Hell!") 是 17,所以我不知道除了纯粹的运气之外是什么终止了 printf,但 memcpy 通常是最符合标准的复制方法从一种表示到另一种表示的数据。
  • 不是运气不好,linux上的bss数据初始化为零,零是空字节AFAIK的ascii值。但这不是这里要问的。造成混乱是我的坏事。
  • 附带说明:如果源和目标内存缓冲区重叠,您可以使用memmove 而不是memcpy。与memcpy 相比,memmove 允许缓冲区重叠。
  • 请注意 (size_t)memcpy(arr, pointer, (size_t)16); 中不需要转换。为了让一些警告符号的迂腐编译器安静下来,可以使用16u。第二种选择:memcpy(arr, pointer, sizeof arr);
  • @PiyushSingh: sizeof(arr) 是 16,您将 16 个字符存储到数组中,没有空终止符。 “Linux 上的 bss 数据”注释是无关紧要的,它是 C 标准,它要求将静态和全局变量初始化为零,因此除非您竭尽全力告诉编译器违反此要求,否则它们将为零。由于memcpy 很好,并且通过char* 为指针别名也很好,这是(在编辑之前)你唯一的问题,这就是我说它的原因。

标签: c pointers printf


【解决方案1】:

拨打memcpy 没问题。您有未定义行为的地方在这里:

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

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

即使类型匹配,您也会仍然拥有 UB,因为 arr 不够大,无法包含字符串 "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 *,因此取消引用该指针以访问原始对象的底层字节是合法的。

【讨论】:

  • 我重新编辑了我的代码 sn-p 以表明我想要明确的内容。在这种情况下,将 uni32_t * 类型转换为 char * 是否非法?
猜你喜欢
  • 2021-06-24
  • 2020-11-04
  • 1970-01-01
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多