代码之家  ›  专栏  ›  技术社区  ›  Petr Skocik

泛型表达式中指向A-VLA类型控制表达式的指针

  •  0
  • Petr Skocik  · 技术社区  · 2 年前

    为什么这个静态断言不会在主要编译器上触发?

    void test(int x){
        _Static_assert(_Generic( (char(*)[x])0, 
        char (*)[1]: 1, default: 0),"");
    }
    

    https://gcc.godbolt.org/z/E67a79oPT

    指向可变长度数组的指针是否应该与指向固定长度数组的指针兼容?

    0 回复  |  直到 2 年前
        1
  •  4
  •   dbush    2 年前

    事实上,它们是相容的。

    首先,第6.7.6.2p6节 C standard 关于数组类型的兼容性说明如下:

    对于要兼容的两种阵列类型,两者都应具有兼容的 元素类型,如果两个大小说明符都存在,则 整数常量表达式,则两个大小说明符应具有 相同的常量值。如果在上下文中使用这两种数组类型 这就要求它们是兼容的,如果 两个大小说明符的计算结果不相等。

    由此可知,如果两个数组大小都是整数常量表达式(即两者都不是VLA),则它们必须相同。然而,如果一个是VLA,这不适用,因此这使它们兼容。

    此外,第6.2.7p3节对复合材料类型进行了如下说明:

    复合类型可以由以下两种类型构成: 可共用的它是一种与这两种类型都兼容的类型 并满足以下条件:

    • 如果两种类型都是数组类型,则应用以下规则:
      • 如果一个类型是已知常量大小的数组,那么复合类型就是该大小的数组。
      • 否则,如果一个类型是可变长度数组,其大小由未计算的表达式指定,则行为为 未定义。
      • 否则,如果一个类型是指定大小的可变长度数组,则复合类型是该大小的可变长度数组。
      • 否则,如果一个类型是未指定大小的可变长度数组,则复合类型是未指定大小的可变长度数组 大小
      • 否则,这两种类型都是大小未知的数组,而复合类型是大小未知的数组。复合材料的元素类型 类型是两种元素类型的组合类型。

    这意味着在比较类型时 char(*)[x] char(*)[1] ,它们的复合类型是 字符(*)[1] .这也意味着 字符(*)[x] 与兼容 任何 指向固定大小数组的指针 char .如果你的函数是这样的:

    void test(int x){
        _Static_assert(_Generic( (char(*)[x])0, 
          char (*)[2]: 2, 
          char (*)[1]: 1, 
          default: 0),"");
    }
    

    由于控制表达式与多个选项兼容,即使这些选项彼此不兼容,也会出现编译错误。

        2
  •  2
  •   Eric Postpischil    2 年前

    它们是兼容的。C 2018 6.7.6.2 6表示,对于要兼容的两种数组类型,两者都应具有兼容的元素类型,如果两个大小说明符都存在,并且都是整数常量表达式,那么两个大小说明符应具有相同的常量值,因为两个大小说明符都不是整数常量表达式,具有相同值的要求不适用。

    指针兼容性继承自指向类型。