【问题标题】:Comparing two different types of pointer比较两种不同类型的指针
【发布时间】:2018-04-24 02:41:03
【问题描述】:

在 C 编程中,像这样比较两种不同类型的指针:

int i = 1;
double d = 2.5;

int *ip = &i;
double *dp = &d;

if(ip != dp) // is it UB?
    printf("Not same\n");

ip != dp 在 C 中是未定义的行为吗?

【问题讨论】:

  • 1.为什么不自己查标准呢? 2. 你为什么要这样做?
  • 是的,我花了整整 40 秒才找到。 port70.net/~nsz/c/c11/n1570.html#6.5.9p2
  • @EugeneSh。那么你的答案是什么,UB,实现定义,有效且始终不相等?
  • 引用如下:两个操作数都是指向兼容类型的合格或不合格版本的指针;
  • 这是 C 语言中的constaint 违规。 IE。您发布的代码无效。它不能编译为 C。这是标准的责任范围结束的地方。其他一切都只是您特定编译器的怪癖。

标签: c pointers types compare


【解决方案1】:

直接比较 ip != dp 在 C 中无效。!= 运算符的规范不允许在一个比较中混合 int *double * 指针。这是 C 中的约束冲突(又名“编译错误”)。符合标准的 C 编译器会通过发出诊断消息来报告您的代码无效。

接下来会发生什么完全取决于您的编译器。与C语言无关。

将此代码称为“产生未定义行为的 C 代码”会产生误导。这在形式上是正确的,但它与说“战争与碎片”的文本是“产生未定义行为的 C 代码”(在一些接受它的奇怪 C 编译器中)一样有意义。

这里的关键是这个代码语言限制意味着它根本不是C代码。

【讨论】:

  • 有些人认为约束不是“句法和语义规则”的一部分:它们不是句法,并且标准始终将约束与语义分开列出。在这种情况下,6.5.9/2 是一个约束,而 6.5.9/3 ff。是语义。这些人说应该发出诊断,并且代码应该按照标准其余部分的规定运行。在大多数情况下,这会通过遗漏导致 UB,但在这种特殊情况下 6.3.2.3(指针转换)可以应用
  • @MM:是的。那时我可能误用/误解了“语义规则”的概念。但是,我看不到 6.3.2.3 与这种情况的相关性。 6.3 不以任何方式暗示这些转换适用于它们可以适用的任何时候。如果 6.5 中的单个运算符(在本例中为 6.5.9),则隐式转换的适用性由规范定义/限制。而且我在 6.5.9 中看不到任何允许在此上下文中进行隐式指针转换的内容。
【解决方案2】:

是的,这个操作是未定义的,Kernighan 和 Ritchie 在他们的《C 编程语言》一书中提到了这一点:

任何指针都可以有意义地与零进行相等或不相等的比较。但是对于算术或与不指向同一数组成员的指针的比较,行为是未定义的。

这意味着不能检查指向不同类型的指针是否相等。

【讨论】:

  • 是否“不能检查指向不同类型的相等性。”适用于比较void *char *?我怀疑在这种情况下是一个例外。
  • K&R 不是 C 标准
  • MM你是对的,但我的动机是提供对 rsp 的参考以供进一步阅读。
【解决方案3】:

没有明确定义。 != 运算符的先决条件是,如果两个操作数都是指针,它们必须是兼容类型。 intdouble 不是兼容的类型。

来自C standard 的第 6.5.9 节:

2 应满足以下条件之一:

——两个操作数都有算术类型;

两个操作数都是指向合格或不合格版本的指针 兼容类型;

——一个操作数是指向对象类型的指针,另一个是 指向 void 的合格或不合格版本的指针;或

——一个操作数是一个指针,另一个是一个空指针常量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-30
    相关资源
    最近更新 更多