为何在scanf中传入&a[i].name会触发类型不匹配警告?
关于scanf中字符数组参数的类型疑问解答
为什么加&a[i].name会触发警告?
a[i].name是长度为10的char数组的数组名。在C语言的表达式中(除sizeof、&操作符等少数场景外),数组名会自动隐式转换为指向数组首元素的指针,也就是char*类型,这正好匹配scanf的%s格式符要求的参数类型——%s需要接收一个指向字符数组起始位置的指针,用来存储输入的字符串。- 当给
a[i].name加上&取地址操作符后,&a[i].name的类型变成了char (*)[10](指向长度为10的char数组的指针),这个类型和%s要求的char*不兼容,因此编译器会抛出类型不匹配的警告。
为什么普通变量要加&,数组却不用?
- 对于普通变量(比如
a[i].roll这类int变量),变量名代表的是变量存储的值,如果要让scanf把输入写入变量的内存地址,必须用&取地址,得到int*类型的指针,匹配%d格式符的参数要求。 - 数组名的特性特殊:它在表达式中会自动转换成指向首元素的指针,相当于已经提供了数组的起始地址,所以不需要额外加
&。虽然a[i].name和&a[i].name的地址数值完全相同,但它们的类型语义不一样——前者指向单个字符,后者指向整个长度为10的字符数组。
额外验证
你可以在代码中加入下面的打印语句,观察地址值和类型的区别:
printf("a[i].name的地址:%p,类型为char*\n", a[i].name); printf("&a[i].name的地址:%p,类型为char (*)[10]\n", &a[i].name);
运行后会发现两个地址的数值完全相同,但编译器对它们的类型判定是不一样的。
内容的提问来源于stack exchange,提问作者Suba
相关产品推荐
相关产品推荐

