2010-08-17 91 views
7

我有以下程序。但是,我不明白为什么我必须传递数组的地址。当他们都指向同一个地址时。这是int数组的第一个元素的地址。为什么我不能直接在C中将指针分配给指针?

我得到一个警告,当我尝试做这个 “不兼容的指针类型赋值”:

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

+0

我试图重写你的标题,因为它没有意义。请确认我是否正确选择了问题的要点。 – 2010-08-17 16:40:09

+0

我觉得你的标题听起来比我的好。谢谢。 – ant2009 2010-08-18 02:06:52

+0

你的代码片段编译得很好。你的意思是如果你将'ptr = var'添加到main中,你会得到一个错误? – 2015-07-21 14:56:58

回答

17

这纯属类型问题。

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

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

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

是的,指针具有相同的地址值(数组第一个元素的地址是数组本身的地址),但它们有不同的类型(int* vs int(*)[5]),因此在赋值中不兼容。

ISO/IEC 9899:1999 6.3.2.1/4:

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

+0

我以为数组在函数中调用时只会衰减为指针。所以在表达中。 int arr [5] = {1,2,3,4,5}; int * ptr = arr;当分配给指针时,arry会衰减为指针吗? – ant2009 2010-08-18 06:43:33

+0

@robUK:这不仅仅是函数调用,它是发生衰减的大多数表达式上下文。用于初始化指针时数组会衰减;需要一个指针值来初始化一个指向“int”的指针,而不是一个“int”数组。 – 2010-08-18 09:09:34

3

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

1

从我可以告诉你分配一个数组指针(var)为指向数组的指针((*ptr)[5])的指针,所以这就是为什么你会得到警告。

相反,尝试使用

int *ptr = NULL; 
4

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

这正是你的情况。该函数采用int (*)[5]类型的参数。这意味着你必须通过该类型的参数。不允许传递int *。地址是否一样无差别。

相关问题