指向数组的指针与数组具有相同的值

时间:2015-03-20 08:11:27

标签: c arrays pointers

下面的代码创建一个数组和一个指向它的指针。然后程序打印出两个变量的内容。奇怪的是,打印出的内存地址是相同的,即使它们不应该。 ptr应包含array地址,而不是array本身。有人可以解释一下吗?

#include <stdio.h>

int main() {

    char array[] = "abcdefg";
    char (*ptr)[] = &array;

    printf("%p\n", array);
    printf("%p\n", ptr);
}

4 个答案:

答案 0 :(得分:1)

对于名为array的任何数组,array&array具有相同的值 - 数组的第一个元素的地址。只是他们的类型不同 - array此处的类型为char *,其中&array的类型为char(*)[]

答案 1 :(得分:0)

例如,将数组视为char a[10];

当我们分配指针变量时,我们指定为char *ptr=a

我们也可以分配像ptr=&a[0];这样两个语句相同,两个语句将引用数组的起始地址

答案 2 :(得分:0)

根据Eli Bendersky的Pointers to arrays in C

  

考虑以下代码:

void test(int** p)
{
}

int main()
{
    int arr[] = {30, 450, 14, 5};
    test(&arr);
    return 0;
}
     

gcc对此并不感到高兴,并发出警告:passing arg 1 of test from incompatible pointer type。 C ++有更严格的类型   检查,让我们尝试通过g++运行相同的代码。如   我们得到一个错误:cannot convert int (*)[4] to int** for argument 1 to void test(int**)

     

那么这里的问题是什么?上面的代码有什么问题?好,   一切。它只是无效,没有任何意义。有些人会   认为它应该有效,因为这有效:

void test(int* p)
{

}

int main()
{
    int arr[] = {30, 450, 14, 5};
    test(arr);
    return 0;
}
     

但是这个特别有效,因为C编译器应该遵循   C标准,要求阵列&#34;衰变&#34;当指针时   用作左值。因此,指向数组的第一个元素的指针是   实际上通过测试,一切正常。

     

但是,第一个代码段是不同的。虽然数组名称可以   衰减成指针,数组的地址不会衰减成a   指向指针的指针。为什么要这样呢?它有什么意义呢?   如此处理数组?

     

有时会传递指针指针来修改指针   (简单的指针参数不能在这里工作,因为C传递值,   这只会允许修改指向的内容,而不是指针   本身)。这是一些虚构的代码(不会编译):

void test(int** p)
{
    *p = malloc ... /* retarget '*p' */
}

int main()
{
    int arr[] = {30, 450, 14, 5};
    int* ptr;

    /* Fine!
    ** test will retarget ptr, and its new value
    ** will appear after this call.
    */
    test(&ptr);

    /* Makes no sense!
    ** You cannot retarget 'arr', since it's a
    ** constant label created by the compiler.
    */
    test(&arr);

    return 0;
}
     

指向数组的指针

     

请注意,可以稍微修改原始代码以使其成为可能   工作:

void test(int (*p)[4])
{
    (*p)[2] = 10;
}

int main()
{
    int arr[] = {30, 450, 14, 5};

    test(&arr);
    printf("%d\n", arr[2]);

    return 0;
}
     

奇怪的类型测试现在接受什么?跟一个&#34;指向你好   array&#34;,C的无用功能之一。这就是C FAQ所具有的功能   说来:

     
    

2.12:如何声明指向数组的指针?

         

通常,你不想。当人们随便说一个指针时     一个数组,它们通常表示指向其第一个元素的指针。

  
     

虽然上一个代码段的测试功能可以编译并运行,   它没有多大用处,因为写起来要清楚得多:

void test(int* p)
{
    p[2] = 10;
}

...
...
/* then call */
test(arr);
     

指针作为函数参数的主要用途是要么避免   按值传递整个结构,或修改指向的对象   指针。两者都是指向数组指针的无关需求。这里&#39; S   一个澄清片段:

int joe[] = {1, 2, 3, 4};

void test(int (*p)[4])
{
    /* Fine: assign to an element through the
    ** pointer.
    */
    (*p)[2] = 10;

    /* Works, but won't be reflected in the
    ** caller since p was passed by value.
    */
    p = &joe;

    /* Error: arrays can't be assigned.
    */
    *p = joe;
}
     

无论如何都不通过值传递数组,因此指向数组的指针是   没用就是为了这个目的。也不能修改数组   杀死第二个原因。

要回答这个问题,&array等于array的原因是因为array是由编译器创建的常量标签,&#34;不是指针变量。因此,对于&#34; dereference&#34;实际上没有任何意义。 array并且只要发生这种情况,编译器就会简单地返回array本身的值。

答案 3 :(得分:-1)

array没有地址,就像ptr有地址一样。因为阵列总是指向相同的存储器位置,所以不需要将该存储器位置存储在某些其他存储器位置中。我无法取array并获得char**的临时(*char)[0] == 'a'

因此&array的类型为char(*)[],并返回数组中第一个char的位置。同样地,array在指针上下文中使用时(也就是说,几乎无处不在,有几个例外),与&array具有相同的效果,但具有不同的类型。这被称为&#34;阵列衰减&#34;。

What is array decaying?的更多信息。