为什么这个指针解除引用的例子有效?

时间:2017-05-01 00:51:51

标签: c arrays pointers struct casting

我有一些代码,它有效,但我不明白为什么。这里:

// This structure keeps the array and its bookkeeping details together.
typedef struct {
    void** headOfArray;
    size_t numberUsed;
    size_t currentSize;
} GrowingArray;

// This function malloc()'s an empty array and returns a struct containing it and its bookkeeping details.
GrowingArray createGrowingArray(int startingSize) { ... }

// Self-explanatory
void appendToGrowingArray(GrowingArray* growingArray, void* itemToAppend) { ... }

// This function realloc()'s an array, causing it to double in size.
void growGrowingArray(GrowingArray* arrayToGrow) { ... }

int main(int argc, char* argv[]) {
    GrowingArray testArray = createGrowingArray(5);

    int* testInteger = (int*) malloc(1);
    *testInteger = 4;

    int* anotherInteger = (int*) malloc(1);
    *anotherInteger = 6;

    appendToGrowingArray(&testArray, &testInteger);
    appendToGrowingArray(&testArray, &anotherInteger);

    printf("%llx\n", **(int**)(testArray.headOfArray[1]));

    return 0;
}

到目前为止,一切都按照我的意图行事。令我困惑的是这一行:

printf("%llx\n", **(int**)(testArray.headOfArray[1]));

根据我的理解,printf()的第二个参数没有意义。我主要通过反复试验来解决问题。它告诉我,好像我说结构中指针数组的第二个元素是指向int的指针。不是。它只是指向int的指针。

对我有意义的是:

*(int*)(testArray.headOfArray[1])

我的理解是结构中包含的指针数组的第二个元素将由最后一个括号提取,然后我将其转换为指向整数的指针,然后取消引用该指针。 / p>

我的理解有什么不对?编译器如何解释这个?

1 个答案:

答案 0 :(得分:0)

我最好的猜测是你的appendToGrowingArray看起来像这样:

void appendToGrowingArray(GrowingArray* growingArray, void* itemToAppend) {
    growingArray->headOfArray[growingArray->numberUsed++] = itemToAppend;
}

虽然显然有额外的逻辑来实际增长箭头。但问题是itemToAppend存储在headOfArray指向的数组中。

但是,如果你查看appendToGrowingArray来电,就会传递testIntegeranotherInteger地址 - 这些已经指向整数,因此,当您真正打算存储指向整数的指针时,您将指向指向headOfArray中整数的指针。

因此,当您考虑testArray.headOfArray[1]时,它的值是变量main的{​​{1}}堆栈上的地址 。当您第一次取消引用它时,它现在指向您存储在anotherInteger中的第二个malloc调用返回的缓冲区的地址。所以,只有当你第二次推荐它到达那个缓冲区的内容,即6号时才会这样做。

你可能想写:

anotherInteger

代替。

(如评论中所述,你也应该修复你的mallocs;这些天你需要超过1个字节来存储一个整数!)