2017-09-02 10 views
0

私はコンパイルしようとしているJon Eriksenの本から取られたポインタを使ってこの単純なコードを手に入れましたが、gccは実行時にコンパイルとセグメント化の失敗(コアダンプ)の警告を出します。ポインタに関する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

さらに、%pを使用してprintfを使用する場合は、hacky_pointerの代わりにint_arrayを直接使用する必要があります。 – leyanpan

+0

大変お世話になりました。私はそれをあなたのアドバイスで動作させることができました:私は "unsigned int"から "long unsigned int"に変更し、アドレスが変数に収まるようにしました。また、printf()関数の型キャストを "hacky_nonpointer "(to *(void *)" hacky_nonpointer "へ)。 – IDK

答えて

1

のように宣言されなければならない。このプログラムは間違っている、と本の中で与えられたアドバイスはobviouであることを考慮してください間違っている。ポインタはポインタに変換できますが、結果は実装定義です。 ポインタへのポインタは、そのような型が存在する場合、intprt_tに変換することができ、を返し、次にを無効ポインタに変換することができます。これは、標準規格による唯一の保証です。他のものは1つのプラットフォームまたは別のプラットフォームで動作するかもしれませんが、ポータブルではありません。大規模なプログラムで使用する理由はありません。

%pには、引数としてvoidへのポインタが必要です。 intに合格すると、未定義の動作が発生します。プログラムで試行され

の事は全くCに移植性表現することはできませんが、おそらくより正確なプログラムがhacky_nonpointer = hacky_nonpointer + sizeof(int);は、すべての上に作者の意図通りに動作することを保証

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

    } 
} 

しかし何もないだろうプラットフォーム。しかしながら、それは多くの通常のシステム、すなわちラズベリーパイ、普通のARMアーキテクチャ、現代のx86-32とx86-64などがあります。


この本はあなたにCを教えるものではなく、Cが彼の意見であるべきものについての誤った解釈を教えています。

0

お使いのOSは、64ビットアーキテクチャを持ち、コンパイラが32ビットである - ベースのコンパイラ! このため、整数とポインタのサイズの不一致があります(組み込み関数sizeof()を使用してチェックできます)。
整数を使用する代わりに、他のデータ型(64ビット長または長整数など)を使用して試してみてください。これもコンパイラに依存します。警告は削除されます。

0

エラーメッセージは十分にクリアです。ポインタのサイズは、intのサイズより大きくすることができます。

あなたのコンパイラはC99とヘッダ<stdint.h>でタイプuintptr_tは、その後、プログラムはその出力はC標準(7.20.1.4から

[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 

ように見えるかもしれません

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

のように見えることができますサポートしている場合オブジェクトポインタを保持できる整数型)

次のタイプvoidへの有効なポインタがこの型に変換することができる 性と符号なし整数型を示し、 は次にvoidへのポインタに変換し、その結果、元のポインタに等しい を比較する:

uintptr_t 

はC標準に従ってパラメータなし機能main

int main(void)