代码1:
unsigned int *p = malloc(sizeof *p);
memset(p, 0x55, sizeof *p);
unsigned int u = *p;
代码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)是:
访问其存储值的对象的有效类型是对象的声明类型(如果有) . 如果通过具有非字符类型的左值的值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及不修改该值的后续访问的有效类型储值 . 如果使用memcpy或memmove将值复制到没有声明类型的对象中,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型是复制值的对象的有效类型(如果有) . 对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型 .
然而,目前还不清楚 memset
是否像写字符类型的左值或其他东西一样 . memset
(7.24.6.1)的描述并不是很有启发性:
memset函数将c的值(转换为unsigned char)复制到s指向的对象的前n个字符中 .
1 回答
我的50ct:
首先,我将其分解为句子以便于参考:
用于访问其存储值的对象的有效类型是对象的声明类型(如果有) .
如果通过类型不是字符类型的左值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及不修改的后续访问的有效类型储存的 Value .
如果使用memcpy或memmove将值复制到没有声明类型的对象中,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型为复制值的对象的有效类型(如果有) .
对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型 .
脚注可能会有所帮助:"87) Allocated objects have no declared type." .
DNA:“不适用”
情况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
.结论:没有违规,但解释是实现定义的,因为实际值取决于变量和endianess内的对齐 .
案例2:
*(double *)d = 1.23;
:2:d
为此以及后续读取变为double *
.memset(d, 0x55, 50);
:与案例1相同 .unsigned int u = *(unsigned int *)d
:d
仍然double *
:砰!在任何情况下,
memset()
都可以用于非char
标量,除非使用0
,它仍然是依赖于实现的,因为(float)0.0
和空指针都不需要实际为"all bits zero" .Finally:
句子2不适用于
memset
,在内部,memset()
由char复制:"...of c (converted to an unsigned char) into each of the first n characters ..."(或至少使用char
语义;实际实现与此无关) .句子3也不适用于
memset()
,因为这仅适用于memcpy
/memmove
或复制为"an array of character type" . 它也没有(但前者这样做,所以or
-condition只是使一个显式的复制循环等效于函数) .memset()
不会更改对象的有效类型 . 这与memcpy
和memmove
不同 . 这是由句子4产生的,它不包括"... for that access and for subsequent accesses ..."为2和3状态,1表示 .希望有所帮助 . 建设性的批评欢迎 .