C 为什么数组索引和地址与分配给数组的字符串具有相同的值?
我写了一些代码,但它给了我一些奇怪的结果C 为什么数组索引和地址与分配给数组的字符串具有相同的值?,c,arrays,C,Arrays,我写了一些代码,但它给了我一些奇怪的结果 #include <stdio.h> #include<string.h> int main() { char r[]={"1dam"}; printf(" %s \n %s ",r,&r); return(0); } 指针具有相同的值(指向相同的地址),但类型不同 一个(r)是char*,另一个(&r)是char(*)[5](指向5个字符数组的指针)。一个好的编译器会警告您,%s无法处理c
#include <stdio.h>
#include<string.h>
int main()
{
char r[]={"1dam"};
printf(" %s \n %s ",r,&r);
return(0);
}
指针具有相同的值(指向相同的地址),但类型不同 一个(
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);
}
我必须编辑我的常规选项,这将提供:
$ 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
$
数组的名称(在您的示例中,数组r
)通常计算为数组第一个元素的地址,因此r
和&r
具有相同的值(但类型不同,因此r+1
和&r+1
在数组长度超过1个元素时将不相等)
如果数组已定义为类型数组[size]
,则数组名称将衰减为类型*
。对该变量的任何递增/递减操作将导致指针以类型
字节的步长移动
&r
的计算结果是相同的地址,但给出了相同的定义,它创建了一个类型为类型(*)[size]
(指向大小的数组的指针)类型)(请参阅C
中的复杂声明的处理)――即它是指向数组的指针,而不是指向单个元素的指针。如果增加这个指针,它将增加整个数组的大小,而不是单个元素的大小
但是,对于声明为指向TYPE
(TYPE*ptr)的指针的变量,不会发生同样的情况。您可以运行下面给出的程序。在下面的程序中,我已经打印了r
、&r
、ptr
和&ptr
的地址。您可以看到r
和&r
的地址相同(但类型不同)。但是,ptr
和&ptr
有不同的地址(它们也有不同的类型。ptr
是char*
类型,&ptr
是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;
}
但是,编译上述代码(在我的Linux
机器上)会发出警告
test.c:7:9:警告:格式“%s”要求参数类型为“char”,但参数3的类型为“char()[5]”[-Wformat=]
printf(“%s\n%s\r\n”,r,&r)
r
作为一个数组,将作为其地址传递给printf
。所以把它的地址写成&r
在这里是没有用的。“它给了我一些奇怪的结果”-->你怎么觉得奇怪?您期望得到什么?请注意printf(“%s”,&r)代码>是UB<代码>“%s”
需要字符指针,而不是指向字符数组的指针。第二个参数调用未定义的行为。在现代工具链/库上,您应该得到警告。如果没有,请启用警告(顺便说一句,您应该在发出请求之前启用并修复警告)。不要忽视警告!看起来像是复制品:但我会让你确认的。@Jean-Françoisfare:同意-因此作为复制品关闭。谢谢你指出这一点,尽管我注意到它是另一个答案中某个链接的副本,并且在你发表评论前几秒钟关闭为副本。很好。不过,这并不是一个很常见的重复。对SO 2528328的x-ref的捕捉很好(为什么数组的地址等于它在C中的值)。
$ 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
$
#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