假设以下示例:
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_a
和ptr_b
包含myArr
的地址对我来说非常清楚。
但我实际上会假设,ptr_c
会包含存储myArr
地址的某种地址(类似于ptr_test
)。
那么,为什么ptr_c
(或ptrptr_c
)包含myArr
的地址?
答案 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_c
为uint8**
除外。 有一种常见的误解,指针指针与数组有某种关系。这是完全错误的,它们与数组无关。这种误解的根源是这样的查找表:
int** pptr = malloc(n*sizeof(*pptr));
...
pptr[i] = malloc(n*sizeof(*pptr[i]));
糟糕的书籍/教程/老师倾向于说上面是2D阵列,但事实并非如此。
请参阅Correctly allocating multi-dimensional arrays以取消这种不正确的信念。它还解释了一些数组指针。
答案 1 :(得分:2)
为什么again
?您应用相同代码的2倍。
它不关心什么类型的变量以及你赋予它的内容。您为ptr_c
和ptrptr_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_a
和ptr_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