在动态 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];
有效类型的规则对 memcpy
和 memmove
(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.
- 问题一:
memset
调用后array
中存储的数据的有效类型是什么?
- 问题 2:
array[0]
访问是否因此违反了严格的别名?因为 _Bool
不是从严格的别名规则中排除的类型(与字符类型不同)。
memset
不会 更改有效类型。 C11 (C17) 6.5p6:
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
. ]
由于值存储 一个 lvalue
在 memset
中具有字符类型,而不是 从中复制字节另一个具有字符类型 左值的对象(该子句将 memcpy
和 memmove
等同于显式 for
循环!),它不会得到一个有效类型,通过array
.
访问的元素的有效类型为_Bool
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");
}
}
with array[0]
作为任何参数 - 为了避免编译时优化,这是单独编译的。当使用 -O3 编译时,会打印以下消息:
both true
true
并且在没有任何优化的情况下
both false
both true
true
false
就严格的别名而言,这段代码的行为是否定义明确?
_Bool* array = malloc(n);
memset(array, 0xFF, n);
_Bool x = array[0];
有效类型的规则对 memcpy
和 memmove
(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.
- 问题一:
memset
调用后array
中存储的数据的有效类型是什么? - 问题 2:
array[0]
访问是否因此违反了严格的别名?因为_Bool
不是从严格的别名规则中排除的类型(与字符类型不同)。
memset
不会 更改有效类型。 C11 (C17) 6.5p6: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
ormemmove
, 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 withmemcpy
,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 dereferencingarray
. ]
由于值存储 一个
访问的元素的有效类型为lvalue
在memset
中具有字符类型,而不是 从中复制字节另一个具有字符类型 左值的对象(该子句将memcpy
和memmove
等同于显式for
循环!),它不会得到一个有效类型,通过array
._Bool
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"); } }
with
array[0]
作为任何参数 - 为了避免编译时优化,这是单独编译的。当使用 -O3 编译时,会打印以下消息:both true true
并且在没有任何优化的情况下
both false both true true false