scanf中&运算符的使用:字符数组场景下的编译器行为疑问
关于字符数组与
scanf中&运算符的疑问解答 嘿,这个问题问到点子上了!C语言里数组和指针的微妙关系确实容易让人困惑,咱们一步步拆解清楚:
先明确几个核心概念
首先得搞清楚数组名、&数组名、单个元素的&这三者的区别:
- 对于
char s[100];:s本身:在大多数表达式场景下(比如函数传参),数组名会自动隐式转换成指向数组首元素的指针,也就是等价于&s[0],类型是char*——这也是你代码里scanf("%s", s)能正常工作的原因,因为%s刚好需要一个char*类型的指针来存储字符串的起始地址。&s:这可不是什么双重指针!它的类型是char (*)[100],翻译过来是「指向包含100个char的数组的指针」。它的地址值和s、&s[0]完全相同(数组的起始地址就是首元素的地址),但类型本质上不一样。&ch:对于单个字符变量char ch;,&ch的类型是char*,这和&s[0]是同一种类型,所以scanf("%c", &ch)是标准的正确写法。
为什么scanf("%s", &s)看起来也能工作?
这其实是个「巧合」:虽然&s的类型是char (*)[100],和%s要求的char*不匹配,但因为两者的地址值完全一致,scanf在内部把这个地址当作char*使用时,刚好指向数组的首元素,所以能正确把字符串写入数组。
但要注意:这种写法是不推荐的!编译器通常会抛出「指针类型不兼容」的警告,而且这是依赖于编译器实现的行为,不是C标准保证的——换个编译器或者平台,说不定就出问题了。
再说说「双重指针」的误区
你担心的「双重指针」是char**类型,它指向的是一个char*类型的指针。而&s是指向整个数组的指针,和char**完全不是一回事。举个例子:
char* p = s; // 合法,s转成char* char** pp = &p; // 合法,&p是char** char (*arr_ptr)[100] = &s; // 合法,类型匹配 // char** pp = &s; // 非法!类型不匹配,编译器会报错
回到你的代码
你的代码里:
scanf("%c",&ch);:正确,&ch是char*,符合%c的要求。scanf("%s",s);:正确,s自动转成char*,符合%s的要求。scanf(" %[^\n]%*c",sen);:正确,sen同样转成char*,%[^\n]用来读取整行(跳过前面的空白),%*c吃掉换行符,写法没问题。
总结一下
- 数组名在函数传参时会自动转成首元素指针,直接传数组名给
scanf("%s")是标准且推荐的写法。 &数组名得到的是指向整个数组的指针,不是双重指针,类型和首元素指针不同,但地址值相同。- 虽然
scanf("%s", &s)可能运行正常,但属于类型不匹配的不规范写法,应该避免。
内容的提问来源于stack exchange,提问作者Harsh Bhudolia
相关产品推荐
相关产品推荐

