C中无索引数组的引用

C中无索引数组的引用,c,arrays,pointers,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; // --> Addr

假设以下示例:

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_测试

那么,为什么ptr_c或ptrpr_c包含myArr的地址呢?

为什么?同一代码应用两次


它不关心什么类型是变量以及您为其分配了什么。将相同的值分配给ptr_cand和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

}

数组在C中,可以衰减-请参阅

这意味着在下文中,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;
}
美元/aa ptr_a:0x7fffdda58cf0 ptr_b:0x7fffdda58cf0 ptr_c:0x7fffdda58cf4 ptr_d:0x7fffdda58cf0 ptr_e:0x7fffdda58cf0 不要在同一行上声明多个变量。或者你会写一些bug,比如uint8*ptr_a,ptr_b,ptr_c,ptr_test;只有第一个变量被声明为指针。 ptr_c=&myArr不是有效的指针转换,因为&myArr的类型是uint8*[4],一个数组指针。数组指针与任何其他指针类型一样工作,尽管它指向整个数组。所以我的数组指针+1给你下一个数组,就像我的指针+1给你下一个指针一样

数组指针指向整个数组,因此它将包含第一项的地址。这就是为什么myArr和&myArr提供相同的地址,但类型不同

不能将数组指针指定给普通指针。如果没有警告/错误,则不应编译此行

ptrptr_c=&myArr;是相同的无效指针转换,但ptrptr_c是uint8**。 有一种常见的误解,即指向指针的指针与数组有某种关联。这完全是错误的,它们与数组无关。这种误解的根源是这样的查找表:

int** pptr = malloc(n*sizeof(*pptr)); 
...
pptr[i] = malloc(n*sizeof(*pptr[i]));
糟糕的书籍/教程/老师往往会说上面的是2D数组,而事实并非如此

一定要忘记这个错误的信念。它还稍微解释了数组指针

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被隐式转换,从uint8的类型4元素数组衰减为指向uint8的指针,表达式的值是数组中第一个元素的地址-这相当于写入&myArr[0]

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

最后,&ptr_a的类型是指向uint8的指针


main返回int,而不是void-使用int main void代替void main。

uint8*ptr_a、ptr_b、ptr_c、ptr_test;这是错误的。uint8*ptr_a、*ptr_b、*ptr_c、*ptr_测试;这是正确的。或:typedef uint8_t*uint8_p;uint8 ptr_a、ptr_b、ptr_c、ptr_test;。您的选择。ptr_a=&myArr[4];//迈尔的地址……绝对不是。。。。最有可能是ptr_的地址是指针…认真对待编译器的警告。修复代码,直到不再出现任何问题。在修复时,不要盲目地丢弃任何警告。除了myArr本身,没有保存myArr地址的不同变量。数组名可以被视为计算到第一个元素的地址,在大多数上下文中,sizeof是一个闪亮的例外。ptr_a=&myArr[4];//myArr的地址,否它是&myArr[4]的地址,元素实际上超出了边界,myArr数组的最后一个元素是myArr[3]。ptr_a=&myArr[4];没有错,评论是错的。对于ptr_b