我们为什么要在C / C ++中使用指针到数组?

时间:2013-12-14 06:33:15

标签: c pointer-to-array

#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 ++中的各种用法?请给我一个真实的例子。

我们可以避免这些复杂而模糊的指针用法吗?

3 个答案:

答案 0 :(得分:3)

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

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数组,它需要更少的分配和释放,因此您不太可能获得它错了,等等。)

答案 1 :(得分:0)

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

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

void HW0_init() { printf("HW0_init\n"); }
void HW0_read() { printf("HW0_read\n"); }
void HW0_write(){ printf("HW0_write\n"); }

void HW1_init() { printf("HW1_init\n"); }
void HW1_read() { printf("HW1_read\n"); }
void HW1_write(){ printf("HW1_write\n"); }

现在想象你想要启动你的模块并从中读取它,所以你可以:

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

答案 2 :(得分:-1)

指针指针(因此通过代理指向数组指针)非常有用。如果你有一个函数/方法并且它需要一个指向值的参数,你可以改变函数内部的值,并且当你离开函数时该值仍然在范围内 - 当然是通过引用传递。但是,您无法更改指针指向的地址 - 例如使您传递给NULL指针的指针,或将其指向内存中其他位置的不同值。如果你使用指针到指针的值,那么你可以改变&#39;中间值的值。你的函数内的指针。我认为MySQL C-connector库是一个使用它的例子。

在您的例如,你可以通过ptrToAnOneDimArray成一个函数,使* ptrToAnOneDimArray是空指针或指向某些其他数据而不是intArrayOne - 为intArrayOne的大小是固定通过编译器(在堆栈上),然后您可以动态地将堆栈中的* ptrToAnOneDimArray更新为堆上的数组malloc()&#39; 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);

}