【问题标题】:Assigning a pointer to a larger array to a pointer to a smaller VLA将指向较大数组的指针分配给指向较小 VLA 的指针
【发布时间】:2019-05-13 14:18:45
【问题描述】:

我注意到 C 编译器(gcc、clang、tinycc)允许我将指向较大数组的指针分配给指向较小 VLA 的指针而不会发出警告:

#include <stdio.h>
#if !__TINYC__
void take_vla(int N, char const X[1][N]) { printf("%zd\n", sizeof(*X)); }
#endif
int main()
{
    static char bigarray[]="0123456789abcdefghijklmnopqrstuvwxyz";
    //VLA
    int n = 3;
    char const (*subarray2)[n]=&bigarray;
    //char const (*subarray3)[(int){3}]=&bigarray; //VLA but clang doesn't see it as such (a bug, I guess)
#if !__TINYC__
    take_vla(3,&bigarray);
    take_vla(3,&"abcdefg");
#endif

    #if 0
        char const (*subarray1)[3]=&bigarray; //-Wincompatible-pointer-types
    #endif
}

这是符合 C 的吗?为什么?

【问题讨论】:

  • 在 C 中,指针只是 CPU 的数字,没有关于它们指向什么的额外信息,并且该语言也没有定义任何元数据,所以没关系关于它所指向的大小,只是类型相同(这是编译器的东西而不是 CPU 的东西)。
  • 在您的subarray2 声明中,n 仅用于地址计算,不会导致存储分配,例如在subarray2++ 中,将添加n 字符的大小。可以认为,当分配的指针指向与n 大小不同的对象时,编译器可能会发出警告,但是,这将是运行时问题,通常不是编译时间问题。
  • @Skizz 是的,但是对于 C 的类型系统,它从未如此简单,不是吗。尝试将最后一个 #if 0 更改为 #if 1 并且您会收到有关该分配的警告(较大的普通旧数组到较小的普通旧数组)。如果“指针只是数字”无关紧要,但对于编译器来说它确实如此。
  • @Skizz:在 C 中,指针只是指向 CPU 的数字,这既是因为它们具有类型信息(这会影响 C 中的指针运算),也是因为 they are abstractions .
  • 代码不严格符合 C,因为赋值运算符的约束 (C 2018 6.5.16.1 1) 说这两个指针必须是指向兼容类型版本的指针,以及可能指向的规则两种兼容的数组类型(6.2.7 3)在不同指定长度的数组的情况下不提供。 (在这种情况下,“指定”包括通过评估其大小表达式确定的长度。)

标签: c arrays language-lawyer c11


【解决方案1】:

const char[3]char[37] 不兼容。

“指向限定类型​​的指针”也不与“指向类型的指针”兼容——不要将它与“限定类型的指针”混为一谈。 (遗憾的是,常量正确性不适用于数组指针。)

相关部分是简单赋值规则C17 6.5.16.1:

  • 左操作数具有原子、限定或非限定指针类型,并且(考虑到 左操作数在左值转换后的类型)两个操作数都是 指向兼容类型的合格或非合格版本的指针,以及指向的类型 to by left 具有所有由 right 指向的类型的限定符;

查看各种编译器:

  • “gnu 模式”中的 gcc 对于检查 C 一致性是没有用的。您必须使用-std=cxx -pedantic-errors 进行编译。之后 gcc 表现良好:gcc -std=c17 -pedantic-errors:

    错误:指向具有不同限定符的数组的指针在 ISO C [-Wpedantic] 中不兼容

  • icc 提供与 gcc 相同的诊断,它工作正常。

  • clang -std=c17 -pedantic-errors 不报告错误,因此它显然不符合 C 标准。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-02
    • 2019-04-20
    • 2018-05-16
    • 2014-08-23
    • 2017-05-15
    • 2016-04-19
    • 2014-07-22
    • 2011-12-04
    相关资源
    最近更新 更多