Lun*_*din 9 c memset strict-aliasing language-lawyer
在严格别名方面,这段代码是明确定义的行为吗?
_Bool* array = malloc(n);
memset(array, 0xFF, n);
_Bool x = array[0];
Run Code Online (Sandbox Code Playgroud)
有效类型的规则具有memcpy
和memmove
(C176.5§6)的特殊情况,但不适用于memset
.
我认为有效的类型就变成了unsigned char
.因为第二个参数memset
需要转换为unsigned char
(C17 7.24.6.1)并且由于有效类型的规则,(C176.5§6):
...或者被复制为字符类型数组,然后该访问的修改对象的有效类型以及不修改该值的后续访问是从中复制值的对象的有效类型,如果它有一个.
array
后存储的数据的有效类型是memset
什么?array[0]
访问是否违反了严格的别名?因为_Bool
不是严格别名规则中排除的类型(与字符类型不同).memset
并不会改变有效类型.C11(C17)6.5p6:
用于访问其存储值的对象的有效类型是对象的声明类型(如果有).[事实显然并非如此.已分配的对象没有声明的类型.]
如果通过具有非字符类型的左值的值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及不修改该值的后续访问的有效类型储值.[不是这种情况,因为使用了字符类型的左值
memset
!]如果 使用或将值复制到没有声明类型的对象中,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型是有效类型复制值的对象,如果有的话. [这里也不是这种情况 - 它不会被复制,或者是一个字符数组]
memcpy
memmove
memcpy
memmove
对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型. [因此,这必须适用于我们的情况.请注意,这适用于将其作为字符内部访问
memset
以及解除引用array
.]
由于该值存储用的lvalue
是内部有字符类型memset
,而不是从与字符类型的左值另一个对象复制的字节数(该条款存在等同memcpy
,并memmove
执行相同操作的使用显式for
循环!),它并没有得到有效的类型,有效的元素类型是_Bool
通过访问array
.
C17标准中可能有一些部分未被指定,但这肯定不是其中之一.
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");
}
}
Run Code Online (Sandbox Code Playgroud)
与array[0]
任何参数一样 - 为了避免编译时优化,这是单独编译的.使用-O3编译时,打印了以下消息:
both true
true
Run Code Online (Sandbox Code Playgroud)
而没有任何优化
both false
both true
true
false
Run Code Online (Sandbox Code Playgroud)