如果全局变量和函数同名会发生什么?

Plo*_*uff 1 c linker gcc function global-variables

众所周知,函数和变量不能同名。
像这样 :

#include<stdio.h>
int main;
int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是由 'main' 重新声明为不同类型的符号引起的。
但是以下两个文件可以成功编译,让我感到困惑。主文件:

void print_main(void);

int main() {
    print_main();
    return 0;
}

Run Code Online (Sandbox Code Playgroud)

打印_main.c

#include <stdio.h>

char main;

void print_main() {
    printf("Output: 0x%x\n", main);    //Output: ffffffe9
}

Run Code Online (Sandbox Code Playgroud)

困惑

  • 我想知道为什么编译器没有提醒我将“main”重新声明为不同类型的符号?
  • 为什么我得到一个奇怪的数字“ffffffe9”,它是什么?
  • 为什么当我在另一个 IDE 上运行这些文件时奇怪的数字会改变?

我试过的

  • 事实上,我知道这是由全局变量“main”和函数“main()”同名引起的。
    所以,这里发生了一些有趣的事情。
  • 在 Visual Studio 2019 上编译并运行它?输出是“ffffffe9”。
    但是在 CLion 上编译并运行它,输出将是“0x55”
  • 当我尝试检查变量“main”的地址时?我发现它与函数“main()”的地址相同。
    像这样

主文件

void print_main(void);

int main() {
    printf("%p\n", &main);   // 003D12BC 
    print_main();            
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

打印_main.c

#include <stdio.h>

char main;

void print_main() {
    printf("Output: %x\n", main);   //ffffffe9
    printf("%p\n", &main);          //003D12BC
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ger 6

几天前我似乎回答了基本相同的问题。哦等等,我做到了。如果对方的 OP 接受了答案,我会将当前的问题作为一个骗局结束。

概括:

  • 符合标准的编译器必须诊断一个翻译单元中相同标识符的不兼容声明,但不需要为不同翻译单元中的声明诊断该问题。

  • 在任何一种情况下,符合标准的编译器都不需要拒绝程序,无论它是否发出诊断信息,但如果它接受它,则程序具有未定义的行为。

  • 我想知道为什么编译器没有提醒我将“main”重新声明为不同类型的符号?

没有义务这样做(见上文),单独编译使得这样做具有挑战性。归根结底,这是一个实施质量问题。

  • 为什么我得到一个奇怪的数字“ffffffe9”,它是什么?

两个词:未定义的行为。

  • 为什么当我在另一个 IDE 上运行这些文件时奇怪的数字会改变?

再次:未定义的行为。

试图深入研究程序未定义行为在不同 C 实现中的各种表现方式并没有多大用处。相反,编写行为定义明确的程序。尤其不要编写您知道其行为未定义的程序。