C语言指针数组疑问:为何argv[0]打印字符串而非内存地址?
关于C语言argv[0]打印行为的疑问
我搞不懂C语言里这个意外的行为:打印argv[0]时输出的是./a.out,但我预期的是内存地址——因为argv是一个指针数组啊。
我创建char name[] = "hello"时,name[0]的值是h,这符合预期。那既然char * argv[]存储的是指针(也就是内存地址),逻辑上argv[0]应该是一个内存地址才对。
我的逻辑是,要访问argv[0]指向的内存地址里的实际内容,应该用*(argv[0])才对。这到底是怎么回事?C语言是不是有什么特殊处理?
+------+------+------+---+---+----+ | h | e | l | l | o | \0 | +------+------+------+---+---+----+ ^---- name[0] = h +------+------+------+ | 0xA7 | 0xCE | 0xC4 | +------+------+------+ ^---- argv[0] = 应该是0xA7(即`argv[0]`本身的值, 而非它指向的内容)
#include <stdio.h> int main(int argc, char * argv[]) { char name[] = "hello"; printf("%c \n", name[0]); // 预期输出h printf("%s \n", argv[0]); // 预期输出0xA7(但实际得到./a.out) }
$ gcc main.c $ ./a.out arg1 arg2 arg3
核心原因:printf的格式控制符决定了输出内容
你混淆了变量本身的值和格式控制符对变量的解析方式,这不是C语言对argv的特殊处理,而是printf的行为规则:
对于
name[0]和%c:name是字符数组,name[0]是数组的第一个元素,类型为char。%c格式符会直接输出该char类型的值,也就是字符h,符合预期。对于
argv[0]和%s:argv是char*类型的数组,argv[0]本身确实是指向字符串的指针(内存地址),但%s格式符的作用是接收字符串指针,输出该指针指向的以\0结尾的字符串内容。如果要打印argv[0]本身的内存地址,需要用%p格式符:printf("%p \n", argv[0]); // 输出类似0x7ffeefbff5a0的内存地址关于
*(argv[0]):*(argv[0])是argv[0]指向的内存地址中的第一个字符,用%c打印会输出程序名的首字符,比如./a.out的首字符.:printf("%c \n", *(argv[0])); // 输出.
补充说明
argv数组的每个元素都是char*类型,指向以\0结尾的字符串:
argv[0]指向程序的路径/名称字符串argv[1]到argv[argc-1]指向各个命令行参数字符串argv[argc]为NULL指针
内容的提问来源于stack exchange,提问作者Martin Zeltin
相关产品推荐
相关产品推荐

