为什么要在 C/C++ 中使用指向数组的指针


#include<stdio.h>
#define SIZE 3
int main()
{   
    char intArrayOne[SIZE] = {'A', 'B', 'C'};
    char (*ptrToAnOneDimArray)[SIZE] = &intArrayOne;
    int i = 0;
    for(i=0 ; i<SIZE ; i++)
    {
        printf("%c ", (*ptrToAnOneDimArray)[i]);
    }
}
Output
A B C 

我们什么时候应该使用"ptrToAnOneDimArray" - C/C++中的各种用法?请给我一个真实世界的例子。

我们能避免这些复杂和模糊的指针用法吗?

例如,当您要实现动态多维数组时:

int (*ptrArr)[WIDTH] = malloc(sizeof ptrArr[0] * HEIGHT);

int **ptrPtr = malloc(sizeof ptrPtr[0] * HEIGHT);
for (size_t i = 0; i < HEIGHT; i++) {
    ptrPtr[i] = malloc(sizeof ptrPtr[0][i] * WIDTH);
}

出于各种原因(它实际上指向内存中连续的 2D 数组,它需要较少的分配和释放,因此您出错的可能性较小,等等(

假设你是嵌入式程序员。现在,您有一些带有可更换模块的硬件。对于每个模块,您必须以不同的方式进行通信,即。您以不同的方式初始化/读取/写入/从中写入。

现在,您的软件必须处理所有这些模块类型。您有 3 个例程(此处简化(来初始化、读取、写入每个类型模块(HW0 是模块 A,HW1 是模块 B(。

void HW0_init() { printf("HW0_initn"); }
void HW0_read() { printf("HW0_readn"); }
void HW0_write(){ printf("HW0_writen"); }
void HW1_init() { printf("HW1_initn"); }
void HW1_read() { printf("HW1_readn"); }
void HW1_write(){ printf("HW1_writen"); }

现在想象一下,你想初始化你的模块并从中读取 sth,所以你这样做:

int hw_id = 1;
// want to init hardware
switch(hw_id)
{
    case 0: HW0_init(); break;
    case 1: HW1_init(); break;
    // ...
}
// now I want to read
switch(hw_id)
{
    case 0: HW0_read(); break;
    case 1: HW1_read(); break;
    // ...
}

使用指向数组的指针可以以不同的方式完成此操作。如果您像这样声明指向函数的指针数组:

// as many arrays as you have modules
void (*hw0[3])() = { HW0_init, HW0_read, HW0_write };
void (*hw1[3])() = { HW1_init, HW1_read, HW1_write };

您的代码可以简化为:

enum HW_ACTION
{
    HW_INIT = 0,
    HW_READ = 1,
    HW_WRITE = 2
};
// pointer to array of pointers to funcs taking nothing
// and returning nothing
void (*(*f)[3])(void);
// detect hardware and set 'f'
f = &hw1;
(*f)[HW_INIT](); // same as HW1_init(); <=> hw1[HW_INIT]();
(*f)[HW_READ](); // same as HW1_read(); <=> hw1[HW_READ]();

相同的效果 - "更简单的代码"。

对于没有C++编译器的C用户,你可以将其视为poor's man virtual methods,通常使用initreadwrite方法创建基本抽象类,并为每种模块实现它们。

这里的现实生活 http://en.wikipedia.org/wiki/Virtual_method_table。

指针到指针(因此通过代理指向数组的指针(非常有用。如果你有一个函数/方法,并且它需要一个指向值的指针参数,你可以更改函数中的值,并且在你离开函数后该值将保留在范围内 - 当然是按引用传递。但是,您无法更改指针指向的地址 - 例如,将您传递的指针转换为 NULL 指针,或将其指向内存中其他位置的不同值。如果使用指针到指针到值,则可以更改函数中"中间"指针的值。我认为MySQL C连接器库是使用它的一个例子。

在您的示例中,您可以将ptrToAnOneDimArray传递到函数中,并使 *ptrToAnOneDimArray 成为 NULL 指针或指向其他数据的指针,而不是intArrayOne - 因为intArrayOne是编译器(在堆栈上(的固定大小,然后您可以从堆栈动态更新 *ptrToAnOneDimArray 成为堆上的数组 malloc((d。

#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
void display(char* data) {
    int i = 0;
    for(i=0 ; i<SIZE ; i++) {
        printf("%c ", data[i]);
    }
}
void changeMyArgument(char** pointerToPointer) {
    *pointerToPointer = (char*) malloc(SIZE * sizeof(char));
    /* now we use array notation for a change */
    (*pointerToPointer)[0] = 'X';
    (*pointerToPointer)[1] = 'Y';
    (*pointerToPointer)[2] = 'Z';
}
int main() {
    /* intArrayOne is implicitly char* */
    char intArrayOne[SIZE] = {'A', 'B', 'C'};
    char* arraysArePointers = intArrayOne;   
    /* ptrToAnOneDimArray is implicitly char** */
    char** ptrToAnOneDimArray;
    ptrToAnOneDimArray = &arraysArePointers;
    display(*ptrToAnOneDimArray);
    changeMyArgument(ptrToAnOneDimArray);
    display(*ptrToAnOneDimArray);
}   

相关内容

  • 没有找到相关文章

最新更新