为什么我不能直接在C中为指针分配数组?

时间:2010-08-17 16:03:11

标签: c pointers

我有以下程序。但是,我无法理解为什么我必须传递数组的地址。当他们都指向同一个地址时。这是int数组的第一个元素的地址。

当我尝试执行“从不兼容的指针类型分配”时,我收到警告:

ptr = var;

完整的源代码:

void print_values(int (*ptr)[5])
{
    size_t i = 0;
    for(i = 0; i < 5; i++) {
        printf("%d: [ %d ]\n", i, (*ptr)[i]);
    }
}

int main(void)
{
    /* declare a pointer to an array integers */
    int (*ptr)[5] = NULL;
    /* array of integers */
    int var[] = {1, 2, 3, 4, 5};
    /* assign the address of where the array is pointing to (first element) */
    ptr = &var;
    /* Both are pointing to the exact same address */
    printf("var  [ %p ]\n",(void*)var);
    printf("&var [ %p ]\n", (void*)&var);

    print_values(ptr);
    return 0;
}

我使用gcc 4.4.4 c89 -Wall -Wextra -O0

编译代码

4 个答案:

答案 0 :(得分:19)

这纯粹是一个类型问题。

在大多数表达式上下文中,数组的名称(例如var)衰减到指向数组的初始元素的指针,而不是指向数组的指针。 [注意,这并不意味着var是一个指针 - 它非常不是一个指针 - 它只是行为就像指向第一个元素的指针大多数表达式中的数组。]

这意味着在表达式var中通常会衰减到指向int的指针,而不是指向int数组的指针。

由于地址运算符(&)的操作数是一个不应用此衰减规则的上下文(另一个作为sizeof运算符的操作数)。在这种情况下,&var的类型直接从var的类型派生,因此类型是指向5 int数组的指针。

是的,指针具有相同的地址值(数组的第一个元素的地址是数组本身的地址),但它们有不同的类型(int* vs int(*)[5])所以aren'与作业兼容。

ISO / IEC 9899:1999 6.3.2.1/4:

  

除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则表达式的类型为“类型的数组“被转换为类型为”指向类型的指针“的表达式,该表达式指向数组对象的初始元素,而不是左值。 ...

答案 1 :(得分:4)

C是强类型语言。当函数需要类型为int *的参数时,您必须传递类型为int *的参数。不是double *,不是char *,而是int *。即使double *char *中的实际数字地址与您想要传递的数字地址“相同”,它仍然不会改变任何内容 - 您仍然需要传递{{1} }。该语言禁止您传递错误类型的值。

这正是你的情况。该函数采用类型int *的参数。这意味着您必须传递该类型的参数。不允许传递int (*)[5]。地址是否相同也没有区别。

答案 2 :(得分:3)

var本身是指向数组中第一个元素的(*int)。 C中的指针和数组非常相似。将int (*ptr)[5] = NULL;更改为int* ptr = NULL;,将ptr = &var;更改为ptr = var;

答案 3 :(得分:1)

从我可以告诉你的是,将数组指针(var)分配给指向数组指针((*ptr)[5])的指针,这就是你得到该警告的原因。

相反,请尝试使用

int *ptr = NULL;