繁体   English   中英

为什么 GCC 和 Clang 会产生不同的 output 变长数组?

[英]Why do GCC and Clang produce different output with variable length array?

为什么 GCC 和 Clang 使用这个符合 C 的代码产生不同的 output:

int (puts) (); int (main) (main, puts) int main;
char *puts[(&puts) (&main["\0April 1"])]; <%%>

即使使用-Wall -std=c18 -pedantic ,编译器也不会产生任何警告或错误,但程序在使用 GCC 构建时不产生 output但在使用 Clang 构建时打印当前日期

为什么 GCC 和 Clang 使用这个符合 C 的代码产生不同的 output:

 int (puts) (); int (main) (main, puts) int main; char *puts[(&puts) (&main["\0April 1"])]; <%%>

首先,它符合规范的代码,尽管它确实使用了可变长度数组,这是 C11 和 C17 中的可选语言功能。 一些混淆是

  • 使用晦涩的二合字母<%%> ,分别表示与{}相同的意思。
  • 在 function 声明中用括号括起 function 标识符
  • puts的前向声明表明它不是原型
  • function main的 K&R 风格定义
    • 带有 VLA 参数
      • 其维度表达式包含 function 调用
      • 和对另一个参数的引用
  • 对 function main()的参数使用非常规标识符
  • 在具有相同标识符的 object 和 function 的声明中分别使用标识符( putsmain
  • 将标识符main用于程序入口点以外的其他内容 function
  • 索引运算符 ( [] ) 的操作数的常规顺序的反转
    • 另外,索引一个 sting 文字
  • 通过显式 function 指针常量表达式调用 function
  • 带有显式 null 字符的字符串文字
  • 换行符的非常规放置(和遗漏)

一个不太混淆的等价物是

int puts();

int main(
    int argc,
    char *argv[ puts("\0April 1" + argc) ]
) {
}

但是,关于使用 GCC 编译的版本与使用 Clang 构建的版本之间的行为差异的核心问题归结为是否在运行时计算 VLA function 参数大小的表达式。

语言规范说,当 function 参数声明为数组类型时,其类型被“调整”为相应的指针类型。 这同样适用于完整、不完整和可变长度数组类型,但规范并未明确说明不评估维度的表达式。 它确实指定表达式 go 在某些其他情况下未计算,并且它甚至在涉及 VLA 的sizeof表达式的情况下对此类规则进行了例外处理,因此在这种情况下的遗漏可以解释为有意义。

这仅对 VLA 类型的参数有影响,因为只有那些维度表达式的评估才能对机器 state 产生副作用,包括但不限于可观察的程序行为。

GCC 没有在运行时评估 VLA 参数的大小表达式,我倾向于认为这符合标准的意图。 结果,GCC 编译的程序除了以状态 0 退出外什么都不做。

Clang 会在运行时计算 VLA 参数的大小表达式。 尽管我不赞成对规范的这种解释,但我不能排除它。 当它计算大小表达式时,它使用第一个参数的传递值。 当程序在没有 arguments 的情况下运行时,第一个参数的值为 1,结果是标准库的puts function 被调用时带有指向"\0April 1"中的'A'的指针。

int (puts) ();
int (main) (main, puts)
    int main;
    char *puts[(&puts) (&main["\0April 1"])];
{
}

有人遇到了编译器错误; 我只是不确定是谁了。 我不明白为什么任何编译器都会发出代码来评估 VLA 的大小参数作为参数。

clang output 相当奇怪。 为了让它工作,它必须在函数的 scope 中找到main ,但尽管已经遇到了puts的声明,但还是放入了全局puts 通常,您可以在其自己的声明中访问变量。

如果有人在生产代码中这样做,我的回答是:“停止使用 K&R function 定义。”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM