2017-09-02 125 views
0

我已經得到了這個簡單的代碼,它使用了Jon Eriksen的書中的指針,我試圖編譯它,但是當我運行它時,gcc給了我編譯和分段錯誤(core dump)時的警告。關於指針的C代碼

#include<stdio.h> 

int main(){ 
    int i; 
    int int_array[5] = {1, 2, 3, 4, 5}; 
    char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; 
    unsigned int hacky_nonpointer; 

    hacky_nonpointer = (unsigned int) int_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(int); // hacky_nonpointer = (unsigned int) ((int *) hacky_nonpointer + 1); 
    } 

    printf("\n\n\n"); 

    hacky_nonpointer = (unsigned int) char_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", hacky_nonpointer, *((char *) hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); 

    } 
} 

輸出:

command line: "gcc -g -o pointer_types5 pointer_types5.c" 

pointer_types5.c: In function ‘main’: 

pointer_types5.c:16:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 
    hacky_nonpointer = (unsigned int) int_array; 

pointer_types5.c:20:103: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 
    points to %p which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); 

pointer_types5.c:20:47: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘unsigned int’ [-Wformat=] 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); 

pointer_types5.c:29:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 
    hacky_nonpointer = (unsigned int) char_array; 

pointer_types5.c:35:101: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 
er] points to %p which contains the char %c\n", hacky_nonpointer, *((char *) hacky_nonpointer)); 

pointer_types5.c:35:48: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘unsigned int’ [-Wformat=] 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", hacky_nonpointer, *((char *) hacky_nonpointer)); 



command line: "./pointer_types5" 
Segmentation fault (core dumped) 

some more info about my os: 
uname -a : Linux PINGUIN 4.10.0-33-generiC#37-Ubuntu SMP Fri Aug 11 10:55:28 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 
+1

在64位系統上,指針的大小通常是64位,而int的大小通常是32位。現在您想一下如何將64位值(指針)放入32位變量中。 –

+1

另外,當使用printf使用%p時,你應該直接使用int_array而不是hacky_pointer – leyanpan

+0

好吧,謝謝你們。我能夠使它與你的建議一起工作:我從「unsigned int」更改爲「long unsigned int」,這樣地址就可以放入變量中,我也可以在printf()函數中從「hacky_nonpointer 「(void *)」hacky_nonpointer「。 – IDK

回答

1

這個程序是錯誤的,並在書中給出的建議是obviou狡猾的錯誤。指針可以轉換爲指針,但結果是實現定義的。甲指針到空隙可以和被轉換爲intprt_t,如果這種類型的存在,然後再回到的指針到空隙。這是標準給出的唯一保證。其他的東西可能在一個平臺或另一個平臺上工作,但它們根本不可移植 - 沒有理由將它們用於大型程序。

A %p需要指向無效的指針作爲參數。通過int有未定義的行爲。

正在嘗試節目中的東西不能用C便攜表示在所有,但可能是一個更正確的程序是

#include <stdio.h> 
#include <inttypes.h> 

int main(void) { 
    int i; 
    int int_array[5] = {1, 2, 3, 4, 5}; 
    char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; 
    uintptr_t hacky_nonpointer; 

    hacky_nonpointer = (uintptr_t)(void *)int_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", (void *)hacky_nonpointer, *((int *)(void *)hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(int); 
    } 

    printf("\n\n\n"); 

    hacky_nonpointer = (uintptr_t)(void *)char_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", (void *)hacky_nonpointer, *((char *)(void *)hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); 

    } 
} 

然而什麼保證hacky_nonpointer = hacky_nonpointer + sizeof(int);會表現得如筆者預期在每平臺。然而,它將在許多普通系統上工作,即樹莓派,普通ARM體系結構,現代x86-32和x86-64等等。


這本書沒有教你C,它教導作者對他認爲C應該是什麼有缺陷的解釋。

0

您的操作系統具有64位架構和編譯器是一個32位 - 基於編譯器! 由於這個原因,整數和指針的大小不匹配(您可以使用in-built sizeof()函數來檢查)。
代替使用整數的,嘗試與一些其它數據類型(例如,64位長或長很長,這是重新編譯器相關的)和警告(一個或多個)將被移除!

0

錯誤消息已足夠清晰。指針的大小可以大於int的大小。

如果你的編譯器支持C99和頭<stdint.h>類型uintptr_t然後程序可以像

#include <stdio.h> 
#include <stdint.h> 

int main(void) 
{ 
    int i; 

    int int_array[5] = {1, 2, 3, 4, 5}; 

    char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; 

    uintptr_t hacky_nonpointer; 


    hacky_nonpointer = (uintptr_t)(void *)int_array; 

    for (i=0; i < sizeof(int_array)/sizeof(*int_array); i++ ) 
    { 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", 
      (void *)hacky_nonpointer, *(int *) (void *)hacky_nonpointer); 
     hacky_nonpointer = hacky_nonpointer + sizeof (int); // hacky_nonpointer = (unsigned int) ((int *) hacky_nonpointer + 1); 
    } 

    printf("\n\n\n"); 

    hacky_nonpointer = (uintptr_t) (void *)char_array; 

    for (i=0; i < sizeof(char_array)/sizeof(*char_array); i++) 
    { 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", 
      (void *)hacky_nonpointer, *(char *)(void *) hacky_nonpointer); 
     hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); 
    } 

    return 0; 
} 

它的輸出可能看起來像

[hacky_nonpointer] points to 0x7fffffd96da0 which contains the integer 1 
[hacky_nonpointer] points to 0x7fffffd96da4 which contains the integer 2 
[hacky_nonpointer] points to 0x7fffffd96da8 which contains the integer 3 
[hacky_nonpointer] points to 0x7fffffd96dac which contains the integer 4 
[hacky_nonpointer] points to 0x7fffffd96db0 which contains the integer 5 



[hacky non_pointer] points to 0x7fffffd96d90 which contains the char a 
[hacky non_pointer] points to 0x7fffffd96d91 which contains the char b 
[hacky non_pointer] points to 0x7fffffd96d92 which contains the char c 
[hacky non_pointer] points to 0x7fffffd96d93 which contains the char d 
[hacky non_pointer] points to 0x7fffffd96d94 which contains the char e 

C標準(7.20.1.4能夠容納對象指針的整數類型)

以下類型指定與 屬性的任何有效的指針的孔隙可以被轉換爲這種類型的無符號整數類型, 再轉換回指向void,結果會比較 等於原始指針:

uintptr_t 

考慮到,根據C標準的功能main不帶參數應聲明如下

int main(void)