在动态 bool 数组上使用 memset 是否定义明确?

Is it well-defined to use memset on a dynamic bool array?

就严格的别名而言,这段代码的行为是否定义明确?

_Bool* array = malloc(n);
memset(array, 0xFF, n);
_Bool x = array[0];

有效类型的规则对 memcpymemmove (C17 6.5 §6) 有特殊情况,但对 memset 没有。

我认为有效类型变为 unsigned char。因为memset的第二个参数需要转换为unsigned char(C17 7.24.6.1)并且因为有效类型的规则,(C17 6.5 §6):

...or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one.

  1. memset 不会 更改有效类型。 C11 (C17) 6.5p6:

    1. The effective type of an object for an access to its stored value is the declared type of the object, if any. [ This clearly is not the case. An allocated object has no declared type. ]

      If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. [ this is not the case as an lvalue of character type is used by memset! ]

      If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. [ this too is not the case here - it is not copied with memcpy, memmove or an array of characters ]

      For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access. [ therefore, this has to apply in our case. Notice that this applies to accessing it as characters inside memset as well as dereferencing array. ]

    由于值存储 一个 lvaluememset 中具有字符类型,而不是 从中复制字节另一个具有字符类型 左值的对象(该子句将 memcpymemmove 等同于显式 for 循环!),它不会得到一个有效类型,通过array.

    访问的元素的有效类型为_Bool

    C17 标准中可能有部分未指定,但这肯定不是其中之一。

  2. array[0]不会违反有效类型规则。

    这不会使使用 array[0] 的值变得合法。它可以(而且很可能)是一个陷阱值!

    我尝试了以下功能

    #include <stdio.h>
    #include <stdbool.h>        
    
    void f1(bool x, bool y) {
        if (!x && !y) {
            puts("both false");
        }
    }
    
    
    void f2(bool x, bool y) {
        if (x && y) {
            puts("both true");
        }
    }
    
    void f3(bool x) {
        if (x) {
            puts("true");
        }
    }
    
    void f4(bool x) {
        if (!x) {
            puts("false");
        }
    }
    

    with array[0] 作为任何参数 - 为了避免编译时优化,这是单独编译的。当使用 -O3 编译时,会打印以下消息:

    both true
    true
    

    并且在没有任何优化的情况下

    both false
    both true
    true
    false