C编译和执行程序有什么区别?

如果一个expression式的评估在C中导致了未定义的行为,并且该expression式总是在程序执行时被评估(例如,如果它出现在main的开头),那么它是否符合,如果一个实现在编译时拒绝它? 在编译/翻译一个程序和执行它之间,C有区别吗?

我知道有C的口译员。他们如何处理C标准有关这种差异?

示例(读取未初始化的本地)

 int main() { int i; return i; } 

当运行它时,在执行的任何阶段(甚至在调用main之前),程序都可以做一些有趣的事情。 但是当我们甚至没有试图运行它时,也会发生一些有趣的事情吗? 它可以导致编译器本身的缓冲区溢出?

从C11草案:

3.4.3未定义的行为

行为,在使用不可移植或错误的程序结构或错误的数据时,本国际标准对此没有要求

注意可能存在的未定义的行为范围从忽略完全不可预知的结果,在翻译或程序执行过程中以环境特征(有或没有发布诊断消息), 终止翻译或执行发出诊断消息)。

终止翻译被认为是(非规范性)注释中未定义行为的可能后果,因此编译时效果显然不打算排除在外。 规范部分当然允许它 – 它允许任何事情。 因此,如果在编译期间检测到未定义的行为,符合的编译器可以终止翻译。

此外,在$ 4一致性

如果违反约束条件或运行时约束条件之外的“应”或“不得”要求被违反,则行为是不确定的。 未定义的行为在本标准中用“未定义的行为”或者省略任何明确的行为定义来表示。 这三者的重点没有区别。 他们都描述“未定义的行为”。

“翻译时间”和“执行时间”之间在规范性定义或一致性描述中没有区别。 未定义行为的不同“品种”之间没有区别。

另外, ouah指出的缺陷报告#109 可以永远不会被执行的代码调用未定义的行为? 有这样的回应:

[…]如果一个expression式的评估会导致未定义的行为出现在需要一个常量expression式的上下文中,那么包含的程序就不是严格符合的。 而且,如果给定程序的每个可能的执行都会导致不确定的行为,则给定的程序不是严格符合的。

一致的实现不能仅仅因为某些可能的程序执行会导致未定义的行为而不能转化严格符合的程序。 […]

这将表明,如果编译器不能静态地确定所有path导致未定义的行为,则编译器不能使翻译失败。

在C11标准§3.7.1中规定,在术语“ 未定义行为”的定义下:

未定义的行为 :行为,使用不可移植或错误的程序结构或错误的数据,本标准对此没有要求

2注意可能存在未定义的行为范围,包括忽略完全不可预知的结果,以翻译或程序执行的方式performance环境特征(无论是否发布诊断消息), 终止翻译或执行发出诊断消息)

所以我想你可以静态地拒绝包含未定义行为的程序,即使它是有效的。

如果一个实现在编译时拒绝它,它是否符合?

它可能也可能不会。 C标准在§3.4.3节中提到:

C11:3.4.3 未定义的行为

  1. 行为,在使用不可移植或错误的程序结构或错误的数据时,本国际标准对此没有要求

  2. 注意可能存在的未定义的行为范围从忽略完全不可预知的结果, 在翻译或程序执行过程中以环境特征 (有或没有发布诊断消息), 终止翻译或执行发出诊断消息)

所以回答你的问题: 它可以导致编译器本身的缓冲区溢出?

是的,它可以。