Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么这段代码运行时仍然有效,有“&”或没有“&”?_C - Fatal编程技术网

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;

我是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 );
}