如果我初始化了一个全局变量 F,并在 main 函数中打印其值,则将打印 0(因为它应该是(。
但是当我在 main 函数中传递参数 int F 时,以与以前完全相同的方式声明全局变量 F,使用 gcc 打印 F 的值打印 1。
谁能解释为什么会这样?
这是我下面的代码。
#include<stdio.h>
int F;
int main(int F){
printf("F is %dn", F);
return 0;
}
当你的主函数包含一个与全局变量同名的参数时,存根被引用到局部变量..而不是全局变量
#include <stdio.h>
static int F;
int main(){
printf("F is %d", F);
return 0;
}
但是当我在主函数中传递参数int F时?那F
只不过是参数计数,即argc
。
在特殊情况下,您提到了全局F
,您在main()
论点中声明F
是不同的。
int main(int F){ printf("F is %dn", F); return 0; }
在这里printf()
打印1
因为当您像./a.out
一样运行可执行文件时,没有命令行输入1
,它类似于argc
。
您的编译器可能会警告您提供给main()
的参数,使用-Wall
标志进行编译并阅读警告。还要检查main()
原型。来自 C 标准
标准化组织/国际电工委员会 9899:1999
§5.1.2.2.1 程序启动
¶1 程序启动时调用的函数被命名为 main。这 实现没有声明此函数的原型。它应该是 使用不带参数的 intand 返回类型定义:
int main(void( {/* ... */}
或带有两个参数(此处称为 argc 和 argv,尽管任何 可以使用名称,因为它们是它们所在的函数的本地名称 声明(:
intmain(int argc, charargv[]( {/... */}
或同等学历;9(或以其他实现定义的方式。
在您发布的代码中,main
有一个名为F
的参数。在main
中,任何对F
引用该变量,而不是全局变量。
通过使用不正确的变量名称,您使生活变得不必要地困难。大多数情况下,要main
的参数被命名为argc
和argv
- 参数计数和参数值。
int main(int argc, char** argv) { ... }
最好使用有意义的变量名称。使用int F;
作为全局变量也没有意义。命名它,使其有意义。然后,你会遇到问题,就像你做得少得多一样。
你应该使main()
符合标准的要求,你应该打印全局F
以及参数F
:
#include <stdio.h>
int F;
int main(int F, char **G)
{
printf("F is %dn", F);
{
extern int F;
printf("%s: F is %dn", G[0], F);
}
return 0;
}
编译(从源文件quirky43.c
到程序quirky43
(并运行时,我得到:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror quirky43.c -o quirky43
$ ./quirky43
F is 1
quirky43: F is 0
$ ./quirky43 this is why you get command line arguments
F is 9
quirky43: F is 0
$
第一个printf()
是打印第一个参数到main()
(通常称为argc
,但将其称为F
并没有错,只是它是意外的(。 第二个打印全局变量F
(以及程序名称,通常argv[0]
但同样使用G
除了出乎意料之外没有任何问题(。 一组大括号内的extern int F;
意味着该语句块中的F
引用在封闭范围之外定义的变量F
,这意味着文件范围变量F
— 可以注意到,它已正确初始化为0
。 出现1
是因为您调用了没有参数的程序,并且参数计数包括程序名称。 这也是为什么在向命令行添加 8 个参数时打印的值9
的原因。
请注意,另一个很好的编译选项是-Wshadow
:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wshadow quirky43.c -o quirky43
quirky43.c: In function ‘main’:
quirky43.c:6:14: error: declaration of ‘F’ shadows a global declaration [-Werror=shadow]
int main(int F, char **G)
~~~~^
quirky43.c:4:5: note: shadowed declaration is here
int F;
^
cc1: all warnings being treated as errors
$
(在运行macOS High Sierra 10.13.5的Mac上使用GCC 8.1.0进行编译。