在下面的代码中:
struct a {
char name[18];
}customer;
scanf("%s",customer.name);
printf("%s",customer.name);
struct a *pt=&customer; `
由于将数组名称指向该元素的第一个元素,因此customer.name
指向该成员的第一个元素吗?
在一本书中写道,*(customer.name+2)
等同于customer.name[2]
和pt->name[2]
.但是我无法理解这些注释,以及为什么customer.name
scanf()
函数是地址而printf()
函数中不是地址?
在此处的print()
和scanf()
示例中,customer.name
解析为指向数组的第一个元素的指针name
该元素是类型struct a
的变量customer
的成员。
为了消除混淆,在%s
格式说明符的情况下,printf()
预期的参数类型是指向数组的第一个元素的指针。因此,在此printf()
调用的情况下,参数customer.name
是正确的,它是一个指针。
当数组用作函数参数时,它会衰减到指向其第一个元素的指针。在scanf
和printf
两个函数中,参数customer.name
被转换为指针并具有char *
类型。
customer.name
是指向name
字符数组中第一个字符的指针。
customer.name
相当于&(customer.name[0])
customer.name
约定是访问结构中的字符数组的典型方法。
在printf()
%s
格式中,需要指向数组第一个元素的指针。
结构a
、数组name
成员和name[0]
字符在内存中具有完全相同的地址。您可以在以下程序中看到这一点:
#include <stdio.h>
#include <stdlib.h>
typedef struct a {
char name[18];
}customer;
int main()
{
customer bob;
customer *ptr;
scanf("%s",bob.name);
printf("Customer name is: %sn",bob.name);
ptr = & bob;
printf("Memory Address of the bob structure is: %pn", (void *) ptr);
printf("Memory Address of the 'bob.name' is: %pn", (void *) &bob.name);
printf("Memory Address of the 'bob.name[0]' is: %pn", (void *) &(bob.name[0]) );
return 0;
}
输出:
Bob
Customer name is: Bob
Memory Address of the bob structure is: 0x7ffe0d7687e0
Memory Address of the 'bob.name' is: 0x7ffe0d7687e0
Memory Address of the 'bob.name[0]' is: 0x7ffe0d7687e0
在这两种情况下,它都是一个地址。但是,其中一个使用该地址来填充字符串,另一个使用该地址来读取值。
printf
当你使用%s
时,该函数需要该字符串的起始地址。您不应该被int i = 10; printf("%d", i");
变量的哪个值传递给printf
的情况所误解。正如你所看到的,字符串在打印功能中的故事是不同的。
在本例中,在scanf
中,您最终传递了地址,因为数组衰减为指向第一个元素的指针。不会发生这种衰减的一些情况是sizeof
,AlignOf
或运算符&
的地址等)。该指针包含数组第一个元素的地址。
scanf("%s",customer.name);
^^^^
指向数组的第一个元素的指针是char*
,其中包含scanf
将值写入所需内存地址所需的地址。为了澄清一点,您甚至可以等效地传递它:(前面的讨论解释了为什么这是可能的)。
scanf("%s",&customer.name[0]);
在printf
中,它也是一个地址,该地址以与以前相同的逻辑传递,而print
又使用它来print
其中包含的字符,直到到达