有没有办法在没有手动静态分析的情况下判断 C 常量指针是否在 GCC 和 Clang 中进行比较?

Are there any way to tell if comparison between C constant pointers are made in GCC and Clang without manual static analysis?

提问人:7888 提问时间:4/23/2023 最后编辑:7888 更新时间:4/25/2023 访问量:75

问:

这是为了查看哪些代码行受 -fmerge-all-constants 的影响。

例如:

// main.c

#include <assert.h>
#include <stdio.h>

int foo(const int* p){
    const int c[2] = {68,41};
    assert(p != c);
    if(!p)
        return foo(c);
    puts("DONE");
    return 0;
}

int main(void){
    foo(NULL);
}

它应该包括文件名、行和行的内容。这个例子会像 main.c:8 和 . 如果使用宏函数,例如 ,它应该告诉此宏执行与行号和文件名的常量指针比较。assert(p != c);#define min(X, Y) ((X) < (Y) ? (X) : (Y))

我尝试在互联网上搜索,但找不到。

C 指针 GCC Clang 比较

评论

1赞 Andrew Henle 4/23/2023
这确实是一个 XY 问题。这样的工具将用于解决什么实际问题
1赞 John Bollinger 4/24/2023
我什至不明白你在问什么。您是否正在寻找一个编译器选项来通知它(一些)指针比较?或者你想编写一个执行测试的宏?还是别的什么?与其他指针相比,“常量指针”(您似乎是指指向类型的指针)对您来说有什么意义?const
0赞 7888 4/24/2023
@AndrewHenle 查看代码的哪一部分是 -fmerge-all-constants。
0赞 7888 4/24/2023
@JohnBollinger 是的,如果有帮助的话。我不想编写任何代码或宏。
0赞 John Bollinger 4/24/2023
我没有遵循您认为检测任何类型的比较将如何帮助您确定哪些常量或变量在生效时可能会被合并。此外,请注意,限定符与 意义上的“常量”几乎无关。目前还不清楚你为什么会感兴趣。-fmerge-all-constantsconst-fmerge-all-constants

答:

0赞 leek 4/25/2023 #1

根据语言定义,指针参数和本地数组不能具有相同的地址,因此它们总是比较为不相等。pc

局部数组必须具有不同于其他变量的地址(如果使用),包括其他递归级别的 的其他实例,并且指针参数不能作为当前递归级别的局部变量传入,因此永远不能等于 。这与选项无关。ccfoo()pcpc-fmerge-all-constants

如果我编译以下代码:

int foo(const int* p) {
    const int c[2] = {68,41};
    return p != c;
}

使用 ,我在 x86 上得到这样的东西(为简洁起见被截断):gcc -O2 -S -masm=intel

foo:
        mov     eax, 1
        ret

编译器能够推断出它始终为 true,因此它始终返回 1 (),而无需在运行时测试指针。由于除了在可以消除的比较中之外,不使用,因此也可以消除。p != ctruecc

我从你的问题中可以看出,你是在问如何判断编译器是否在比较 和 地址。最好通过查看生成的汇编代码来完成此操作,如上所示,该代码消除了 中的比较。pc-O2

该选项是不安全的,因为它可能会合并不同递归级别的常量局部数组,即使它们以相同的方式初始化,如果使用这些地址,例如将它们传递给另一个函数调用,或将它们与其他地址进行比较,这些数组也必须具有不同的地址。-fmerge-all-constants

但是,编译器可以自由地优化指针比较,无论它是否合并了所有级别的常量数组,因为指针比较可以在语言规则内单独优化,并且对数组最终是否被合并没有影响或依赖性。

通过比较 的地址,您隐含地同意将有一个唯一的地址用于比较目的,无论它实际上最终是否是唯一的。cpc

从文档中:

-fmerge-all-constants

尝试合并相同的常量和相同的变量。

此选项意味着 .除此之外,还要考虑例如,甚至常量初始化 数组或带有整数或 浮点类型。像 C 或 C++ 这样的语言需要每个变量, 在递归调用中包含同一变量的多个实例, 具有不同的位置,因此使用此选项会导致 不合格行为。-fmerge-constants-fmerge-constants

safer 不会合并使用地址的常量变量,也不会合并递归函数中的常量局部变量。-fmerge-constants