我已经写了一些代码,但这给了我一些奇怪的结果。
#include <stdio.h>
#include<string.h>
int main()
{
char r[]={"1dam"};
printf(" %s \n %s ",r,&r);
return(0);
}
输出
1dam
1dam
答案 0 :(得分:2)
指针的值相同(指向相同的地址),但类型不同。
一个(r
)是char *
,另一个(&r
)是char (*)[5]
(指向5个字符的数组的指针)。一个好的编译器会警告您%s
无法处理char (*)[5]
。地址是相同的,但是在每个地址上加一个并打印指针值(%p
并强制转换为(void *)
),您将得到不同的结果。
#include <stdio.h>
int main(void)
{
char r[]={"1dam"};
printf("%s\n%s\n", r, &r);
printf("%p : %p\n", (void *)r, (void *)&r);
printf("%p : %p\n", (void *)(r + 1), (void *)(&r + 1));
return(0);
}
输出(在运行macOS 10.13.6 High Sierra的Mac上,使用GCC 8.2.0):
1dam
1dam
0x7ffeebe8648b : 0x7ffeebe8648b
0x7ffeebe8648c : 0x7ffeebe86490
我不得不编译掉我的普通选项,这给了:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pa31.c -o pa31
pa31.c: In function ‘main’:
pa31.c:6:22: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[5]’ [-Werror=format=]
printf("%s\n%s\n", r, &r);
~^ ~~
cc1: all warnings being treated as errors
$
答案 1 :(得分:0)
数组的名称(在您的情况下为数组r
)通常求值为数组第一个元素的地址,因此r
和&r
的值相同(但类型不同,因此r + 1
和&r + 1
如果数组长度超过1个元素,将不相等。
如果将数组定义为TYPE array[size]
,则数组名称将衰减为类型TYPE *
。对此类变量进行的任何增/减操作都将导致指针以TYPE
个字节为步长移动。
&r
的计算结果是相同的地址,但是给定相同的定义,它会创建类型为TYPE (*)[size]
的指针(指向 size TYPE数组的指针) )(请参阅C
中的this解开复杂的声明)–即,它是指向数组而不是单个元素的指针。如果增加此指针,它将增加整个数组的大小,而不是单个元素的大小。
但是,对于声明为pointer
到TYPE
(TYPE * ptr)的变量,不会发生相同的事情。您可以运行下面给出的程序。在下面的程序中,我打印了r
,&r
,ptr
和&ptr
的地址。您可以看到r
和&r
的地址相同(但它们的类型不同)。但是,ptr
和&ptr
具有不同的地址(并且它们也具有不同的类型。ptr
的类型为char *
,而&ptr
的类型为{{1 }})。
您可以参考this问题来详细了解该概念。
例如,考虑下面给出的程序:
char **
程序的输出为:
#include <stdio.h>
#include <string.h>
int main()
{
char r[] = "1dam";
printf(" %s \n %s \r\n",r, &r);
char *ptr = r;
printf( " Pointers: %p %p \r\n", ptr, &ptr);
printf( " Array: %p %p \r\n", r, &r);
return 0;
}
但是,在我的1dam
1dam
Pointers: 0x7fff4d46cd50 0x7fff4d46cd48
Array: 0x7fff4d46cd50 0x7fff4d46cd50
计算机上编译以上代码会发出警告。
test.c:7:9:警告:格式'%s'期望类型为'char ',但是参数3的类型为'char()[5]'[-Wformat = ] printf(“%s \ n%s \ r \ n”,r,&r);