C 为什么这段代码运行时仍然有效,有“&”或没有“&”?
我是c语言的新手。 我看不出这到底是什么区别。 谢谢你的帮助C 为什么这段代码运行时仍然有效,有“&”或没有“&”?,c,C,我是c语言的新手。 我看不出这到底是什么区别。 谢谢你的帮助 #include<stdio.h> int main(void) { char a[9]; scanf("%s",&a);//scanf("%s",a) printf("%s",&a);//printf("%s",a) they all can run correctly! for(int i=0;i<9;i++) { printf("%c;
#include<stdio.h>
int main(void)
{
char a[9];
scanf("%s",&a);//scanf("%s",a)
printf("%s",&a);//printf("%s",a) they all can run correctly!
for(int i=0;i<9;i++)
{
printf("%c;",a[i]);
}
return 0;
}
使用&,您正在为类型不匹配调用未定义的行为:%s expect char*,但是&a这里有类型char*[9]指向9元素字符数组的指针
在典型的环境中,指针被实现为简单的内存地址。
尽管存在类型不匹配,但数组&a及其第一个元素a的地址将具有相同的大小和值,因此很有可能工作正常。允许进行一些类比
假设你生活在一个半透明的世界里,你有一些不同颜色的激光指针
你用红色激光指向人,蓝色激光指向飞机,黄色激光指向手机
在C俚语中,不匹配指针和未定义行为的对象是非法的,所以飞机上没有黄色激光,人身上没有蓝色激光
现在想象一下,你用黄色激光指向一个在飞机上旅行的人的手机,然后你问一个色盲朋友指针指向的是哪架飞机。你的朋友不在乎颜色,错误地说,这是黄色激光照射到的任何平面
但是错误的责任人是你。你欺骗了你的朋友
不要在以下方面对编译器撒谎:
#include<stdio.h>
int main(void)
{
char a[9];
scanf("%s",&a);//scanf("%s",a)
printf("%s",&a);//printf("%s",a) they all can run correctly!
for(int i=0;i<9;i++)
{
printf("%c;",a[i]);
}
return 0;
}
gcc -O1 -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled2.c"
untitled2.c: In function ‘main’:
untitled2.c:5:13: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[9]’ [-Wformat=]
scanf("%s",&a);//scanf("%s",a)
~^ ~~
untitled2.c:6:14: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[9]’ [-Wformat=]
printf("%s",&a);//printf("%s",a) they all can run correctly!
~^ ~~
untitled2.c:5:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
scanf("%s",&a);//scanf("%s",a)
^~~~~~~~~~~~~~
Compilation finished successfully.
最后一句话:编译成功完成。当出现警告消息时,只意味着编译器针对问题进行了一些“变通”,但这并不意味着编译器生成了您想要的代码
关于:
for(int i=0;i<9;i++)
{
printf("%c;",a[i]);
}
因此,只能输出用户输入,而不能输出未初始化的字节
更好的是,由于使用%s调用scanf将导致NUL终止,因此输入将使用单个语句:
printf( "%s\n", a );
OT:调用任何scanf系列函数时,始终检查返回值而不是参数值,以确保操作成功。注意:这些函数返回成功的“输入格式转换”说明符或EOF的数量。建议:添加语法更正和错误检查后
if( scanf("%8s",a) != 1 )
{ // error occurred
fprintf( stderr, "scanf for input data failed\n" );
exit( EXIT_FAILURE );
}
密切相关:数组在传递给函数时会衰减为指针,因此,尽管您需要scanf%d,&i,但对于数组,您只需要scanf%s,a。我想补充一点,如果在传递给scanf时它只是一个整数,那么您需要引用&a,因为您需要将指针传递给scanf。char a[9]是一个数组,因此a已经是指向数组第一个元素的指针,因此不再需要&。它们是否有相同的输出,您想知道原因吗?或者你只是想知道为什么代码不会崩溃?关于:chara[9];扫描%s,&a;如果输入超过8个字符,结果将是缓冲区溢出,导致未定义的行为。当使用“输入格式说明符%s和/或%[…]时,总是包含一个最大字符修饰符,因为这些说明符总是在输入中附加一个NUL字节。我喜欢这种类比。
if( scanf("%8s",a) != 1 )
{ // error occurred
fprintf( stderr, "scanf for input data failed\n" );
exit( EXIT_FAILURE );
}