在动态布尔数组上使用memset是否定义明确? [英] Is it well-defined to use memset on a dynamic bool array?
问题描述
就严格的别名而言,此代码的行为是否定义明确?
Is this code well-defined behavior, in terms of strict aliasing?
_Bool* array = malloc(n);
memset(array, 0xFF, n);
_Bool x = array[0];
有效类型的规则对于memcpy
和memmove
(C17 6.5§6)有特殊情况,但对于memset
没有特殊情况.
The rule of effective type has special cases for memcpy
and memmove
(C17 6.5 §6) but not for memset
.
我认为有效类型变为unsigned char
.因为memset
的第二个参数需要转换为unsigned char
(C17 7.24.6.1),并且由于有效类型的规则,所以(C17 6.5§6):
My take is that the effective type becomes unsigned char
. Because the second parameter of memset
is required to be converted to unsigned char
(C17 7.24.6.1) and because of the rule of effective type, (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
调用之后,存储在array
中的数据的有效类型是什么? - 问题2:
array[0]
访问是否因此违反严格的别名?由于_Bool
不是严格的别名规则所排除的类型(与字符类型不同). - Question 1: What is the effective type of the data stored in
array
after thememset
call? - Question 2: Does the
array[0]
access therefore violate strict aliasing? Since_Bool
is not a type excluded from the strict aliasing rule (unlike character types). -
memset
不会不更改有效类型. C11(C17)6.5p6: memset
does not change the effective type. 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. ]
推荐答案
如果将值存储到
通过具有以下类型的左值而没有声明类型的对象
是不是字符类型,则左值的类型变为
该访问以及后续访问的对象的有效类型
不会修改存储值的访问. [情况并非如此,因为memset
使用字符类型的左值! ]
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
! ]
如果已复制一个值
使用memcpy
或memmove
或进入没有声明类型的对象
复制为字符类型数组,然后将有效类型
修改的对象,用于该访问以及随后的访问
不修改值是对象的有效类型,从中
如果该值为1,则复制该值.
[这里也不是这种情况-不会用memcpy
,memmove
或字符数组复制]
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 ]
用于对其他所有
没有声明类型的对象,则该对象的有效类型为
只是用于访问的左值的类型. [因此,这在我们的情况下必须适用.请注意,这适用于在memset
中以字符形式访问它以及取消引用array
. ]
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
内部,并且没有从另一个对象复制的字符类型为lvalue的字节 (该子句的存在使memcpy
和memmove
等同于在显式的for
循环中执行相同的操作!),它没有获得有效的类型,并且元素的有效类型为_Bool
通过array
访问.
Since the values are stored with an lvalue
that has character type inside memset
, and not have the bytes copied from another object with lvalues of character type (the clause exists to equate memcpy
and memmove
with doing the same with an explicit for
loop!), it does not get an effective type, and the effective type of elements is _Bool
for those accessed through array
.
C17标准中的某些部分可能未得到充分说明,但这当然不是其中一种.
There might be parts in the C17 standard that are underspecified, but this certainly is not one of those cases.
array[0]
不会违反有效类型规则.
array[0]
would not violate the effective type rule.
使用array[0]
的值不再合法.它可以(而且很可能是)陷阱值!
That does not make using the value of array[0]
any more legal. It can (and will most probably) be a trap value!
我尝试了以下功能
#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");
}
}
以array[0]
作为任何参数-为避免编译时优化,将其分别编译.用-O3编译时,将显示以下消息:
with array[0]
as any of the arguments - for the sake of avoiding compile-time optimizations this was compiled separately. When compiled with -O3 the following messages were printed:
both true
true
并且在没有任何优化的情况下
And when without any optimization
both false
both true
true
false
这篇关于在动态布尔数组上使用memset是否定义明确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!