我对这两个陈述有一个理论上的问题:
假设p
指向Integer和a
Integer 的指针:
a)if(p==a){.....}
或if(p>a)
..
b)p=a
;
所有这些都是非法的,b
特别危险,但标准C如何考虑它们?
阅读标准,我没有发现它们是错误,未定义的行为,未指定的行为,违反约束,如果其中一个是合法的或其他的.
看着无数类似的问题,我还没有找到解决方案.
一切都是非法的.为了进行比较,双方大多数可以转换为普通类型,对于赋值,右侧必须可以转换为左侧的类型,并且:
除了6.5.16.1的约束允许之外,涉及指针的转换应通过显式转换来指定.
(6.5.4,3; 6.5.16.1描述了空指针常量,一些例外void
指针和_Bool
在分配的情况下).
当您添加显式转换以将指针转换为整数时,程序再次变为有效,您将从比较中获得布尔值.结果取决于实现.uintptr_t
在整数存储指针时一定要使用.
C11 (n1570) \xc2\xa76.5.8 [关系运算符] / 2:
\n\n\n\n\n约束条件
\n\n应满足下列条件之一:
\n\n\n
\n- 两个操作数都有实数类型;或者
\n- 两个操作数都是指向兼容对象类型的限定或非限定版本的指针。
\n
(实数类型是指整数类型、枚举、实数浮点类型和char
(\xc2\xa76.2.5/17))
\xc2\xa76.5.9 [相等运算符]
\n\n\n\n\n约束条件
\n\n应满足下列条件之一:
\n\n\n
\n- 两个操作数都具有算术类型;
\n- 两个操作数都是指向兼容类型的限定或非限定版本的指针;
\n- 一个操作数是指向对象类型的指针,另一个是指向;的限定或非限定版本的指针。
\nvoid
或者- 一个操作数是指针,另一个是空指针常量。
\n
\xc2\xa76.5.16.1 [简单赋值] / 1:
\n\n\n\n\n约束条件
\n\n应满足下列条件之一:
\n\n\n
\n- 左操作数具有原子、限定或非限定算术类型,右操作数具有算术类型;
\n- 左操作数具有与右操作数兼容的结构或联合类型的原子、限定或非限定版本;
\n- 左操作数具有原子、限定或非限定指针类型,并且(考虑\n左值转换后左操作数将具有的类型)两个操作数都是\n 指向兼容类型的限定或非限定版本的指针,以及指向的类型\n左边的 to 拥有右边指向的类型的所有限定符;
\n- 左操作数具有原子、限定或非限定指针类型,并且(考虑左值转换后左操作数的类型)一个操作数是指向对象类型的指针,另一个操作数是指向限定的指针或 \n 的非限定版本
\nvoid
,并且左侧指向的类型具有右侧指向的类型的所有限定符;- 左操作数是原子的、限定的或非限定的指针,右操作数是空\n指针常量;或者\n 左操作数的类型为atomic、qualified 或unqualified
\n_Bool
,而右操作数是一个 pointer。
基本上,所有 3 个表达式都违反了表达式中设置的约束。
\n\n违反约束是什么意思?错误?但没有任何地方说违反约束会导致翻译失败。C标准似乎不是很清楚,但最接近的解释是:
\n\n\xc2\xa74 [一致性] / 2:
\n\n\n\n\n如果违反出现在约束或运行时约束之外的 \xe2\x80\x9cshall\xe2\x80\x9d 或 \xe2\x80\x9cshall not\xe2\x80\x9d 要求,则行为未定义。
\n
但这谈论的是约束之外;和 \xc2\xa75.1.1.3 [诊断] / 1:
\n\n\n\n\n如果预处理翻译单元或翻译单元包含违反任何语法规则或约束,即使该行为也明确指定为未定义或实现定义的。在其他情况下不需要产生诊断消息。
\n
所以编译器至少需要产生一条消息(正如我们在 gcc 中看到的那样),但没有说明之后应该做什么。
\n\n本段后面的例子提到
\n\n\n\n\n例子
\n\n实现应为翻译单元发出诊断:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nchar i;\n int i;\n
因为在本国际标准中的措辞将构造的行为描述为约束错误并导致未定义行为的情况下,应诊断约束错误。
\n
和 \xc2\xa76.7 [声明] / 3 没有明确提到违反约束将导致未定义的行为。
\n\n因此,我推断你的3个表达式都是未定义的行为,并伴有诊断消息。
\n