C语言 比较指针和静态变量的行为是什么?



我读到类似指针等于的东西,如果: 它们都指向相同的地址或相同的功能。

它是否适用于名称相同但地址不同的static函数?

主.c

#include <stdio.h>
extern void *p1;
extern void *p2;
int main() {
printf("%dn", p1 == p2);
return 0;
}

static void f() {}

公元前

#include "A.h"
void *p1 = &f;

C.c

#include "A.h"
void *p2 = &f;

这段代码将打印什么,或者可能是未定义的行为?

代码将具有未定义的行为,但正是因为 C 标准没有指定当指向函数的指针转换为指向void的指针时会发生什么。

将指向函数的指针转换为指向void的指针被列为常见扩展 (C11 J.5.7),POSiX 需要它。但是,它可能仍应使用显式强制转换。

仅当指向同一函数

的两个指针指向同一函数时,它们才会相互比较相等 (C11 6.5.9p6)

两个指针比较相等,当且仅 [...],两者都是指向同一对象的指针(包括指向对象的指针和其开头的子对象)或函数,[...]

在不同翻译单元中具有内部链接的两个函数是不同的,因此指向它们的指针应该比较不相等;如果保证往返,它们的void *转换也是如此。


我这样阅读标准,如果链接器将两个定义相同的代码合并,则实现不符合要求。(C11 6.2.2p2)

代码中有 2 个问题:

  • 该函数是在每个模块中static定义的,编译器将为每个模块生成一个不同的对象,链接器可能会也可能不会合并该对象,因为两者具有相同的代码,无论它们static名称如何。但是,这种优化似乎不符合,因此函数应该具有不同的地址。

  • 指针的类型为void *,不能保证明确地容纳函数指针。事实上,C 标准没有定义将指向函数的指针转换为指向对象类型的指针的行为。因此,除非您假设 C 标准的扩展,否则行为是未定义的。您应该使用类型void (*p1)();等定义p1

程序很可能会输出0,但在您修复类型问题之前,不能保证此行为。

最新更新