将unsigned char数组解释为bool数组

tau*_*ran 1 c++ gcc casting boolean

请考虑以下代码.它没问题还是会导致未定义的行为?

#include <iostream>

int main()
{
    {
        unsigned char binary[] = {0, 5, 10};
        bool* x = reinterpret_cast<bool*>(&binary[0]);

        for (unsigned int i = 0; i < 3; ++i)
        {
            std::cout << (x[i] ? 1 : 0) << " ";
        }
    }

    {
        unsigned char b = 255;
        bool* x = reinterpret_cast<bool*>(&b);
        std::cout << (*x ? 1 : 0) << std::endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用gcc 4.6到4.8编译时的输出是

0 5 10 1

但只有优化(-O1和更多).Clang导致

0 1 1 1

即使有优化.现在,如果更改y[i] ? 1 : 0y[i] ? 2 : 1gcc结果

1 2 2 1.

任何想法,还是由于演员而导致的未定义行为?

Rob*_*ahy 6

该标准并不保证bool完全兼容char(即它不保证它们具有相同的尺寸或对齐),并说:

类型的值booltruefalse.

§3.9.1[basic.fundamental]

它还说:

使用bool本国际标准描述的方式中的值为"未定义",例如通过检查未初始化的自动对象的值,可能会使其表现为既不是也不truefalse.

脚注47(N3337)

因此,您处于未定义行为的范畴.

请注意,由于标准没有例外bool,因此适用以下规则:

如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:

- 对象的动态类型,

- 对象的动态类型的cv限定版本,

- 与对象的动态类型类似的类型(如4.4中所定义),

- 与对象的动态类型对应的有符号或无符号类型的类型,

- 对应于对象的动态类型的cv限定版本的有符号或无符号类型,

- 聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员),

- 一种类型,是对象的动态类型的(可能是cv限定的)基类类型,

- char或unsigned char类型.

§3.10[basic.lval]

在这种情况下unsigned char,对象的类型是,因此尝试通过bool左值(通过解除引用a获得bool *)来访问它们会导致UB.