Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.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_Arrays - Fatal编程技术网

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