2016-10-04 65 views
0

我正在嘗試編寫一個函數,該函數按字節指定的大小轉發指針。如何使用函數提高數組基地址?

void 
increment_ptr(void **_ptr, int size){ 
    *_ptr = (char *)(*_ptr) + size; 
} 

int 
main(int argc, char **argv){ 
    int arr[] = {11,20}; 
    printf("%d\n", arr[0]); 
    increment_ptr((void **)&arr, sizeof(int)); 
    printf("%d\n", arr[0]); 
    return 0; 
} 

輸出我得到的是:

[email protected]:~$ ./a.out 
11 
15 

我期待的輸出爲11和20。

任何人可以請幫助?

+0

第二個printf應該打印數組的第二個元素爲20. –

+0

您期望'increment_ptr'以某種方式更改'arr';你能更直接地檢查嗎? –

+0

我明白,它可以直接完成,我已經粘貼了我想要在我的項目中做的簡化版本。所以,請讓它這樣.. –

回答

4

arr不是您可以更改的普通變量。它不是一個指針 - 它的類型是int[2]

試試這個代碼:

#include <stdio.h> 
void 
increment_ptr(void **_ptr, int size){ 
    *_ptr = (char *)(*_ptr) + size; 
} 

int 
main(int argc, char **argv){ 
    int arr[] = {11,20}; 
    int* arr1 = arr; 

    printf("arr is %p\n", (void*)arr); 
    printf("arr1 is %p\n", (void*)arr1); 
    printf("arr gives %d\n", arr[0]); 
    printf("arr1 gives %d\n", arr1[0]); 

    increment_ptr((void **)&arr, sizeof(int)); 
    increment_ptr((void **)&arr1, sizeof(int)); 

    printf("arr is %p\n", (void*)arr); 
    printf("arr1 is %p\n", (void*)arr1); 
    printf("arr gives %d\n", arr[0]); 
    printf("arr1 gives %d\n", arr1[0]); 

    return 0; 
} 

可能的輸出:

arr is 0xfff1d1b8 
arr1 is 0xfff1d1b8 
arr gives 11 
arr1 gives 11 
arr is 0xfff1d1b8 // Notice arr isn't changed 
arr1 is 0xfff1d1bc // arr1 works as expected 
arr gives 15 
arr1 gives 20 

換句話說:你不能提前這樣一個數組的基址

您可能還會發現這代碼有趣:

#include <stdio.h> 

int main(int argc, char **argv){ 
    int arr[2] = {11,20}; 
    printf("arr is %p\n", (void*)arr); 
    printf("arr is %p\n", (void*)&arr); 
    return 0; 
} 

可能的輸出:

arr is 0061FED8 
&arr is 0061FED8 

注意如何打印arr爲指針給出了相同的打印&arr

那麼,在你的代碼的情況是,數11(又名ARR [0])讀作指針(鑄造到char *),然後添加4(因此您有15),它將覆蓋當前的11。注意:這個結果表明指針和int s在你的系統上都是4個字節。

+0

'arr'是一個左值。但是這與 –

+0

這個問題沒有關係@MM - 嗯,好吧,我可能是錯的:-)但是'++ arr'會給出'錯誤:當使用gcc時需要作爲增量操作數需要lvalue' – 4386427

+0

這是來自gcc的一個誤導消息,它應該說「可修改的左值作爲增量操作數」。數組是一個左值,但不是可修改的左值。 –

2

代碼

int arr[2]; 

聲明瞭一個存儲空間。所以,當你獲得它的地址時,它會返回這個存儲空間的基地址,這與arr相同。

這與聲明指針的情況不同。指針是保存地址的變量,但數組只是內存空間。

0

當你聲明一個變量(數組或者不是數組)時,它的地址在該變量的其餘生命週期中保持不變。無法將變量移動到新地址。

您的代碼只會導致未定義的行爲(嚴格別名違規 - *_ptr使用類型void *的左值來訪問聲明爲int的內存)。