我读到类似指针等于的东西,如果: 它们都指向相同的地址或相同的功能。
它是否适用于名称相同但地址不同的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
,但在您修复类型问题之前,不能保证此行为。