Code 1:
unsigned int *p = malloc(sizeof *p);
memset(p, 0x55, sizeof *p);
unsigned int u = *p;
Code 2:
void *d = malloc(50);
*(double *)d = 1.23;
memset(d, 0x55, 50);
unsigned int u = *(unsigned int *)d;
在每种情况下,会产生什么影响memset
具有 malloc 空间中对象的有效类型;初始化也是如此u
正确还是严格的别名违规?
的定义有效型(C11 6.5/6) 是:
The 有效型访问其存储值的对象的类型是该对象的声明类型(如果有)。如果通过类型不是字符类型的左值将值存储到没有声明类型的对象中,则该左值的类型将成为该对象的有效类型,用于该访问以及后续不修改该对象的访问。储值。如果使用将值复制到没有声明类型的对象中memcpy
or memmove
,或被复制为字符类型数组,则该访问以及不修改该值的后续访问的已修改对象的有效类型是从中复制该值的对象的有效类型(如果该对象有一个) 。对于对没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型。
但尚不清楚是否memset
行为就像通过字符类型的左值或其他类型进行写入。的描述memset
(7.24.6.1) 不是很有启发:
memset 函数复制 c 的值(转换为unsigned char
) 到 s 指向的对象的前 n 个字符中的每一个中。
My 50ct:
首先,我将其分成句子以便于参考:
- 访问其存储值的对象的有效类型是该对象的声明类型(如果有)。
- 如果通过类型不是字符类型的左值将值存储到没有声明类型的对象中,则该左值的类型将成为该对象的有效类型,用于该访问以及后续不修改该对象的访问。储值。
- 如果使用 memcpy 或 memmove 将值复制到没有声明类型的对象中,或者复制为字符类型数组,则该访问以及不修改该值的后续访问的已修改对象的有效类型是从中复制值的对象的有效类型(如果有)。
- 对于对没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型。
脚注可能会有所帮助:“87)分配的对象没有声明类型。” http://port70.net/%7Ensz/c/c11/n1570.html#note87.
DNA:“不适用”
Case 1:
-
memset(...)
:1:DNA(未声明类型),2:DNA(memset 写入char
- 语义),3:DNA(既不是 memcpy 也不是 memmove),4:char []
仅适用于内部 memset(不是永久的)。
-
unsigned int u = *p
: 1:DNA(未声明类型),2/3:DNA(不写入,但读取),4:左值的类型是unsigned int
.
结论:没有违规,但解释是实现定义的,因为实际值取决于变量内的对齐方式和字节序。
Case 2:
-
*(double *)d = 1.23;
: 2: d
变成double *
为此和以下阅读。
-
memset(d, 0x55, 50);
:与情况 1 相同。
-
unsigned int u = *(unsigned int *)d
: d
还是double *
: bang!
以任何方式,memset()
对于非char
标量,除非使用0
,这仍然是依赖于实现,因为两者都不是(float)0.0
,也不空指针实际上需要“所有位为零”。
Finally:
- 第 2 句不适用于
memset
,如内部那样,memset()
按字符复制:“... of c(转换为无符号字符)到前 n 个字符中的每一个...”(或使用char
至少是语义学;实际的实现与这里无关)。
- 第 3 句不适用于
memset()
,或者,因为这只适用于memcpy
/memmove
或者复制为“字符类型数组”时。它也没有(但前者这样做,所以or
-condition 只是使显式复制循环等效于函数)。
-
memset()
does not改变有效型的对象。这不同于memcpy
and memmove
。这是第 4 句的结果,它不包括“...用于该访问和后续访问...”,如 2 和 3 状态以及 1 所暗示的那样。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)