C中没有索引的数组的引用

时间:2017-04-13 12:01:27

标签: c arrays pointers

假设以下示例:

uint8 myArr[4] = {0, 1, 2, 3};
uint8* ptr_a, ptr_b, ptr_c, ptr_test;
uint8** ptrptr_c;

void main(void)
{
    ptr_a = &myArr[4];  // Address of myArr
    ptr_b = myArr;      // Address of myArr  
    ptr_c = &myArr;     // --> Address of myArr again?! <---
    ptrptr_c = &myArr;  // --> Address of myArr again?! <--

    ptr_test = &ptr_a   // Address of ptr_a (whose content points to myArr)
}

ptr_aptr_b包含myArr的地址对我来说非常清楚。 但我实际上会假设,ptr_c会包含存储myArr地址的某种地址(类似于ptr_test)。

那么,为什么ptr_c(或ptrptr_c)包含myArr的地址?

4 个答案:

答案 0 :(得分:4)

  • 永远不要在同一行声明多个变量。或者您将编写像uint8* ptr_a, ptr_b, ptr_c, ptr_test;这样的错误。只有第一个变量被声明为指针。
  • ptr_c =&amp; myArr不是有效的指针转换,因为&myArr的类型是uint8 (*)[4]数组指针。数组指针的工作方式与任何其他指针类型一样,但它指向整个数组。因此my_array_pointer+1为您提供下一个数组,就像my_int_pointer+1为您提供下一个int(下一个指向项目)。

    数组指针指向整个数组,因此它将包含第一个项的地址。这就是myArr&myArr给出相同地址(但不同类型)的原因。

    您不能将数组指针指定给普通指针。这行不应该在没有警告/错误的情况下编译。

  • ptrptr_c = &myArr;与无效指针转换相同,但ptrptr_cuint8**除外。

有一种常见的误解,指针指针与数组有某种关系。这是完全错误的,它们与数组无关。这种误解的根源是这样的查找表:

int** pptr = malloc(n*sizeof(*pptr)); 
...
pptr[i] = malloc(n*sizeof(*pptr[i]));

糟糕的书籍/教程/老师倾向于说上面是2D阵列,但事实并非如此。

请参阅Correctly allocating multi-dimensional arrays以取消这种不正确的信念。它还解释了一些数组指针。

答案 1 :(得分:2)

为什么again?您应用相同代码的2倍。

它不关心什么类型的变量以及你赋予它的内容。您为ptr_cptrptr_c分配了相同的值。所以它们都包含相同的值。这通常是错误的概念,编译器应警告您或给您错误。

正确的价值是:

uint8 myArr[4] = {0, 1, 2, 3};
uint8 *ptr_a, *ptr_b, *ptr_c, *ptr_test;
uint8** ptrptr_c;

void main(void) {
    //ptr_a = &myArr[4];  // Address of myArr //WRONG!!!!
    ptr_a = &myArr[3]; //If you want last address, use 3, because 3 is last index.

    ptr_b = myArr;      // Address of myArr, OK!!  

    //ptr_c = &myArr;     // WRONG: if ptr_c is pointer to uint8_t then assing uint8_t pointer to it.
    ptr_c = myArr;      //Correct!

    //This should be compiler error something like:
    //a value of type "uint8_t (*)[]" cannot be assigned to an entity of type "uint8_t **
    ptrptr_c = &myArr;  // Address of myArr again? No, error.

    //This is WRONG
    ptr_test = &ptr_a;   // WRONG:
    ptr_test = ptr_a;    //THIS IS OK

}

答案 2 :(得分:1)

uint8* ptr_a, ptr_b, ptr_c, ptr_test;

只有ptr_a被声明为指向uint8的指针;其他所有内容都被声明为uint8t

根据您的分配,每个变量的正确类型为

uint8 *ptr_a, *ptr_b, (*ptr_c)[4], (*ptrptr_c)[4], **ptr_test;

表达式&myArr[4]具有类型uint8 *,并且计算对象的地址超过数组的最后一个元素(请记住,C中的数组从0开始索引)。

表达式myArr被隐式转换(“衰减”)从类型“{4}元素数组uint8”到“指向uint8的指针”,表达式的值是数组中第一个元素的地址 - 它相当于编写&myArr[0]

由于&运算符的存在,myArr未隐式转换为指针,因此&myArr的类型是指向{{4元素数组'的指针1}}”。数组的地址与数组的第一个元素的地址相同,因此uint8&myArr[0]myArr都将产生相同的值,但不会都有相同的类型。

最后,&myArr的类型是“指向&ptr_a的指针”。

并且,uint8返回main,而不是int - 使用void代替int main( void )

答案 3 :(得分:0)

C中的数组可能会衰减 - 请参阅this answer

这意味着,在下文中,ptr_aptr_b相同(相同)。

另请注意,在下文中,ptr_d的分配无效(请参阅下面的警告)。

#include <stdio.h>
#include <stdint.h>

int main(void) {
    uint8_t myArr[4] = { 0, 1, 2, 3 };

    uint8_t *ptr_a = myArr;
    uint8_t *ptr_b = &(myArr[0]);
    uint8_t *ptr_c = &(myArr[4]);
    uint8_t *ptr_d = &myArr;  /* <-- invalid (warning raised) */

    printf("ptr_a: %p\n", ptr_a);
    printf("ptr_b: %p\n", ptr_b);
    printf("ptr_c: %p\n", ptr_c);
    printf("ptr_d: %p\n", ptr_d);

    return 0;
}
$ gcc aa.c -o aa && ./aa
aa.c: In function ‘main’:
aa.c:9:19: warning: initialization from incompatible pointer type [enabled by default]
  uint8_t *ptr_c = &myArr;
     ^
$ ./aa
ptr_a: 0x7fffdda58cf0
ptr_b: 0x7fffdda58cf0
ptr_c: 0x7fffdda58cf4
ptr_d: 0x7fffdda58cf0
ptr_e: 0x7fffdda58cf0