在动态布尔数组上使用memset是否定义明确? [英] Is it well-defined to use memset on a dynamic bool array?

查看:133
本文介绍了在动态布尔数组上使用memset是否定义明确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is this code well-defined behavior, in terms of strict aliasing?

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

有效类型的规则对于memcpymemmove(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 the memset 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).
    • 推荐答案

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

      1. memset does not change the effective type. C11 (C17) 6.5p6:

      1. 用于访问其存储值的对象的有效类型为 对象的声明类型(如果有). [显然不是这样.分配的对象没有声明的类型. ]

      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. ]

      如果将值存储到 通过具有以下类型的左值而没有声明类型的对象 是不是字符类型,则左值的类型变为 该访问以及后续访问的对象的有效类型 不会修改存储值的访问. [情况并非如此,因为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! ]

      如果已复制一个值 使用memcpymemmove进入没有声明类型的对象 复制为字符类型数组,然后将有效类型 修改的对象,用于该访问以及随后的访问 不修改值是对象的有效类型,从中 如果该值为1,则复制该值. [这里也不是这种情况-不会用memcpymemmove或字符数组复制]

      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的字节 (该子句的存在使memcpymemmove等同于在显式的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆