为什么数组索引和地址与分配给数组的字符串具有相同的值?

时间:2018-09-01 18:23:42

标签: c arrays

我已经写了一些代码,但这给了我一些奇怪的结果。

#include <stdio.h>
#include<string.h>
int main()
{ 
    char r[]={"1dam"};
    printf("  %s \n  %s ",r,&r);
    return(0);
}

输出

1dam
1dam

2 个答案:

答案 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解开复杂的声明)–即,它是指向数组而不是单个元素的指针。如果增加此指针,它将增加整个数组的大小,而不是单个元素的大小。

但是,对于声明为pointerTYPE(TYPE * ptr)的变量,不会发生相同的事情。您可以运行下面给出的程序。在下面的程序中,我打印了r&rptr&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);