C 奇怪的范围外变量

C 奇怪的范围外变量,c,variables,scope,arguments,C,Variables,Scope,Arguments,我在查找命令时发现,使用该函数似乎会莫名其妙地生成另一个名为optarg的变量。你可以看到这样一个例子 #包括/*用于printf*/ #包括/*退出*/ #包括/*用于getopt*/ int main(int argc,字符**argv){ INTC; 整数位数_optind=0; int aopt=0,bopt=0; char*copt=0,*dopt=0; 而((c=getopt(argc,argv,“abc:d:012”)!=-1){ int这个选项=optind?optind:1;

我在查找命令时发现,使用该函数似乎会莫名其妙地生成另一个名为
optarg
的变量。你可以看到这样一个例子

#包括/*用于printf*/
#包括/*退出*/
#包括/*用于getopt*/
int main(int argc,字符**argv){
INTC;
整数位数_optind=0;
int aopt=0,bopt=0;
char*copt=0,*dopt=0;
而((c=getopt(argc,argv,“abc:d:012”)!=-1){
int这个选项=optind?optind:1;
开关(c){
案例“0”:
案例“1”:
案例“2”:
if(digital\u optind!=0&&digital\u optind!=this\u optind)
printf(“数字出现在两个不同的argv元素中。\n”);
数字\u optind=此\u选项\u optind;
printf(“选项%c\n”,c);
打破
案例“a”:
printf(“选项a\n”);
aopt=1;
打破
案例“b”:
printf(“选项b\n”);
bopt=1;
打破
案例“c”:
printf(“值为'%s'\n的选项c”,optarg);
copt=optarg;
打破
案例“d”:
printf(“值为“%s”\n的选项d”,optarg);
dopt=optarg;
打破
案例“?”:
打破
违约:
printf(“?getopt返回的字符代码0%o???\n”,c);
}
}
如果(选项D

请注意,
optarg
现在似乎没有声明或初始化。也许这只是C语言中我不知道的一个常见特性,但我已经在谷歌上搜索了几个小时,我不知道我要找的东西的名字。任何解释都很好。

optarg
中声明,术语是“全局变量”。如果在函数外部声明变量,则可以在函数内部访问该变量:

int i = 7;

int main()
{
    printf("%d\n", i); // prints 7
    return 0;
}
optarg
的情况下,
unistd.h
头将其声明为具有外部链接的全局
char*
变量:

extern char *optarg;
(请参阅手册页中的。

GETOPT(3)                BSD Library Functions Manual                GETOPT(3)

NAME
     getopt -- get option character from command line argument list

LIBRARY  
     Standard C Library (libc, -lc)  

SYNOPSIS  
     #include <unistd.h>  

     extern char *optarg;  
     extern int optind;  
     extern int optopt;  
     extern int opterr;  
     extern int optreset;  

     int  
     getopt(int argc, char * const argv[], const char *optstring);
GETOPT(3)BSD库函数手册GETOPT(3)
名称
getopt——从命令行参数列表中获取选项字符
图书馆
标准C库(libc,-lc)
提要
#包括
外部字符*optarg;
外部-内部选项;
外-内光电转换;
外部内部opterr;
外部内部光路;
int
getopt(int argc,char*const argv[],const char*optstring);

这些变量在
unistd.h
头文件中声明。

如果您找到了名称,但不知道它们的定义或声明位置,请只运行负责
\include
的C预处理器,然后使用
grep
more
搜索术语

比如说

gcc -E foo.c >foo.i
将C预处理器的结果放入foo.i

然后,您可以使用more(使用/to搜索)查看该文件

该文件将引用包含定义或声明的包含文件

比如说,,
更多foo.i

然后
/optarg

显示线路
extern char*optarg

通过向上滚动(或反向搜索
?#
),我可以找到

414”/usr/include/unistd.h“34

-变量:char*optarg

对于接受参数的选项,getopt将此变量设置为指向option参数的值


我在网站上发现它肯定不是-那会违反ODR,不是吗?@KerrekSB我肯定他指的是它在unistd.h中使用extern声明,但在其他地方定义。“外部存储”,比如,在U盘上?@KerrekSB:好的,我现在把它改为“外部定义”。谢谢你的评论。虽然我有点喜欢U盘的想法。:-)@KerrekSB的外部定义不是在您的建筑的编译单元中,而是在您稍后将链接到的编译单元中。我认为该术语是“外部链接”:-(如“标题声明具有外部链接的全局变量”)。@KerrekSB:太完美了,谢谢!现在重新编辑,希望是最后一次。:-)非常感谢。我知道什么是全局变量,但我不知道optarg是统一声明的。h@IrresponsibleNewbWebsearch是回答以下问题的一种非常简单的方法:@DavidHeffernan:或者阅读手册页(当然,假设您使用的是类似unix的系统)。这就是为什么我喜欢这样回答。在这种情况下,bash还提供了一个
optarg
,因此您需要指定手册中的以下部分:
$man 3 optarg
gcc -E foo.c >foo.i