memset编写的对象的有效类型是什么?

时间:2015-06-21 23:14:21

标签: c language-lawyer strict-aliasing

代码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< d;空间中对象的有效类型有什么影响;那么正在初始化u正确还是严格的别名冲突?

有效类型(C11 6.5 / 6)的定义是:

  

用于访问其存储值的对象的有效类型是对象的声明类型(如果有)。如果通过具有非字符类型的左值的值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及不修改该值的后续访问的有效类型储值。如果使用memcpymemmove将值复制到没有声明类型的对象中,或者将其复制为字符类型数组,则为该访问和后续访问修改对象的有效类型不修改值的是从中复制值的对象的有效类型(如果有的话)。对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型。

然而,不清楚memset是否表现得像通过字符类型的左值或其他东西写作。 memset(7.24.6.1)的描述并不是很有启发性:

  

memset函数将c的值(转换为unsigned char)复制到s指向的对象的前n个字符中。

1 个答案:

答案 0 :(得分:7)

我的50ct:

首先,我将其分解为句子以便于参考:

  1. 访问其存储值的对象的有效类型是对象的声明类型(如果有)。
  2. 如果通过具有非字符类型的左值的值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及后续访问的有效类型不要修改储值。
  3. 如果使用memcpy或memmove将值复制到没有声明类型的对象中,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型value是复制值的对象的有效类型(如果有的话)。
  4. 对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型。
  5. 脚注可能会有所帮助:"87) Allocated objects have no declared type."

    DNA:"不适用"

    案例1:

    • memset(...):1:DNA(没有声明的类型),2:DNA(memset写入char - 语义),3:DNA(既不是memcpy也不是memmove),4:{{1}仅限内部memset(非永久性)。
    • char []:1:DNA(没有声明的类型),2/3:DNA(没有写,但是读过),4:左值的类型是unsigned int u = *p

    结论:没有违规,但是解释是实现定义的,因为实际值取决于变量和endianess中的对齐。

    案例2:

    • unsigned int:2:*(double *)d = 1.23;成为d以及以下内容。
    • double *:与案例1相同。
    • memset(d, 0x55, 50);unsigned int u = *(unsigned int *)d仍然是d:bang!

    在任何情况下,double *都可以用于非memset()标量,除非使用的char仍然是依赖于实现的0空指针也不需要实际"所有位为零"。

    <强>最后:

    • 句子2不适用于(float)0.0,在内部,memset副本由char:&#34; ... c(转换为无符号字符)到前n个字符中的每一个...&#34; (或者至少使用memset()语义;这里的实际实现是无关紧要的。)
    • 句子3也不适用于char,因为这仅适用于memset() / memcpy或复制为&#34;字符类型数组&#34;。它也没有(但是前者,所以memmove - 条件只是使一个显式的复制循环等效于函数)。
    • or 更改对象的有效类型。这与memset()memcpy不同。这是由句子4产生的,该句子不包括&#34; ...用于该访问和随后的访问......&#34;如2和3状态和1暗示。

    希望有所帮助。 建设性的批评欢迎。