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

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

4

3 回答 3

4

例如,当你想实现一个动态多维数组时:

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);
}

出于各种原因(它实际上指向一个在内存中连续的二维数组,它需要更少的分配和释放,所以你不太可能弄错,等等)

于 2013-12-14T06:46:31.063 回答
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]();

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

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

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

于 2013-12-14T12:37:39.087 回答
-1

指向指针的指针(因此通过代理指向数组的指针)非常有用。如果您有一个函数/方法并且它需要一个指向值的参数,您可以更改函数内部的值,并且在您离开函数后该值保持在范围内 - 当然是通过引用传递。但是,您不能更改指针指向的地址 - 例如,将您传递的指针设为 NULL 指针,或将其指向内存中其他位置的不同值。如果您使用指向值的指针,那么您可以更改函数内“中间”指针的值。我认为 MySQL C-connector library 就是一个使用它的例子。

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

#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);

}   
于 2013-12-14T13:02:44.247 回答