c - 将字符串文字复制到 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]);
}
}
解决方案
调用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 *
,取消引用该指针以访问原始对象的底层字节是合法的。
推荐阅读
- php - 使用 PHP 将 HTML 复选框列表更改为选择下拉列表
- powershell - 错误:“%_.LastWriteTime 未被识别为 cmdlet 的名称”
- xslt - 根据属性值 xslt 1.0 获取唯一节点
- hyperledger-fabric - 安装 Hyperledger Fabric 二进制文件
- python - 计算整个 DataFrame 中的值的数量
- c - 在句子中按字母顺序对字符串中的字符进行排序
- java - groovy中的日期格式
- javascript - Javascript:使用 Moment js 的自定义日期/时间格式返回“无效日期”
- apache-nifi - NiFi:抓取多个正则表达式匹配(使用 ExtractText 进入属性?)
- haskell - 如何修复这个涉及列表类型外观的导管代码,而我不希望出现这种情况?