将字符串文字复制到uint32_t数组并访问它 [英] Copying a string literal to an uint32_t array and accessing it

查看:323
本文介绍了将字符串文字复制到uint32_t数组并访问它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将下面的代码粘贴到其他位置,但是有人建议将其作为错误的解决方案.标准中关于memcpy的说法是这样的:

I pasted below code else where but it was suggested as a bad solution. The standard has this to say about memcpy:

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

"The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined."

关于uint32_t的信息:

and this about uint32_t:

"typedef名称uintN_t指定了一个宽度为N且不为n的无符号整数类型 填充位.因此,uint24_t表示这样的无符号整数类型,其宽度为 正好是24位."

"The typedef name uintN_t designates an unsigned integer type with width N and no padding bits. Thus, uint24_t denotes such an unsigned integer type with a width of exactly 24 bits."

是否存在对齐问题?我一直在linux上使用它,从未遇到过任何bug或类似问题.当我不得不担心字节序(例如,通过另一种体系结构通过链接接收数据)时,我仅使用按位操作来进行访问.请给点光.

Are there any alignment issues ? I have always been using this on linux and never encountered any bugs or such. I only use bitwise ops for access when i had to worry about the endianness for example receiving data over a link from another architecture. Kindly throw some light.

#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的调用很好.未定义行为的位置在这里:

The call to memcpy is fine. Where you have undefined behavior is here:

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

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

The %s format specifier expects a char * argument but you're passing a uint32_t *. Such an argument mismatch is undefined behavior. The two pointer types may have the same representation on your system, but that isn't necessarily true in general.

即使类型匹配,您也会 still 使用UB,因为arr的大小不足以包含字符串"HelloWorld!Hell!".该字符串(包括null终止字节)的宽度为17个字节,因此不会复制null终止符.然后printf读取数组的末尾,即UB.

Even if the types matched, you would still have UB because arr isn't large enough to contain the string "HelloWorld!Hell!". This string (including the null terminating byte) is 17 bytes wide and so the null terminator isn't copied. Then printf reads past the end of the array which is UB.

作为示例,我修改了变量列表,如下所示:

As an example, I modified the list of variables as follows:

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

并获得以下输出:

HelloWorld!Hell!�wfU

至此:

char *arr1 = (char *)arr;

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

This is legal because a pointer of one object type may be converted to a pointer to another object type. Also, because the destination type is char *, it is legal to dereference that pointer to access the underlying bytes of the original object.

这篇关于将字符串文字复制到uint32_t数组并访问它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆