• ベストアンサー

NULLポインタについて

NULLポインタはどこのアドレスも指さないポインタのことですよね。 printf("%p\n",&NULL);とすると00000000が 表示されます これはアドレスの0番地を指しているということでしょうか? でもNULLのアドレスが0番地なら、NULLポインタはどこのアドレスも指さないポインタというのと矛盾しますよね? アドレスの0番地とNULLは関係ないのでしょうか? よくわからないので教えてください。

noname#132718
noname#132718

質問者が選んだベストアンサー

  • ベストアンサー
  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.5

NULLポインタの意味は「どのアドレスも指していないポインタ」です。 しかし、ポインタ変数は必ずどこかのアドレスを指しています。 (「データの無い変数」は存在しません) そこで、【(絶対に)使われることのないアドレス】として、0番地をNULLポインタとして代用しています。 たいていは #define NULL (void *)0 か #define NULL 0 で定義されています。

noname#132718
質問者

お礼

ありがとうございました。

その他の回答 (4)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.4

&NULL って、何のことなんでしょうか。

noname#132718
質問者

補足

すみません。よく考えたら&はいりませんね。 printf("%p\n",NULL);です 失礼しました

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

NULLマクロは右辺値である空ポインタ定数に展開されますので、(単項の)&演算子のオペランドにはなれないはずです。 処理系が何かわかりませんが、未定義の動作を引き起こしているのでしょう。 > アドレスの0番地とNULLは関係ないのでしょうか? Cの仕様における「アドレス」とハードウェアの「アドレス」は必ずしも一致しませんが、いずれにせよ直接は関係ありません。

noname#132718
質問者

補足

&はいりませんでした。

  • a_kwn
  • ベストアンサー率34% (8/23)
回答No.2

あなたは、C言語の変数に、何か”値”以外のものが入れられると考えているのですか? プログラムを作る上で”無効なポインタの値”を表すものがあると何かと便利なので、NULLという定義が規定されましたが、その値は、有効なアドレス値でない必要があります。 「たまたまあなたの環境で、"0" を無効アドレス値に使えたので」ので、その値を使っているだけです。 (大体、0番地は、プロセスのアドレス空間で有効でない環境が多い)

  • SAYKA
  • ベストアンサー率34% (944/2776)
回答No.1

NULLの実態のアドレスをNULLって定義してるだけじゃない?

関連するQ&A

  • 「NULLポインタ」と「演算の結果としてのアドレス0」との比較

    ものすごく基本的な疑問です。。。 「C言語FAQ日本語訳」http://www.kouno.jp/home/c_faq/ ここの「05.ヌルポインター」を見ると以下のような意味の記述があります。 「NULLポインタは他のどんなポインタの値とも区別可能で、有効なポインタと比較しても等しくなる事はない」 「ポインタを書くべき場所に書かれた定数0はコンパイル時にNULLポインタに変換される」 そこで以下のプログラムを Borland C++ 5.5 for Win32 でコンパイル・実行してみたところ、 p1 == p2 とりました。これって変ですよね? p1 は明示的に定数0で初期化しているのでNULLポインタですが、p2 は演算の結果としてアドレス0番地を指しているので、NULLポインタでは無いですよね? これはコンパイラが間違っていると思って良いのでしょうか? #include <stdio.h> int main() { char *p1,*p2; p1 = 0; p2 = (char *)1; p2--; if(p1 == p2){ printf("p1 == p2"); } else{ printf("p1 != p2"); } return 0; }

  • NULLポインタは0と書かなければだめ?

    C++言語を使っています。 C++言語でNULLポインタを表す場合、0やNULLを使用しますが、 「NULLは単なるマクロなので本来は0を使わなければだめ」という話を聞きました。 つまり、 int *p = 0; が本当の正しいNULLポインタであり、 int *p = NULL; は推奨されていない(?)NULLポインタというようです。 今まであまり疑うことなく、NULLポインタを表すのにNULLを使用していましたが、 上記の内容は本当でしょうか。

  • C言語のNULLについて

    C言語のNULLについて教えてください。 ・NULLは、アドレスの0番地であり、参照先が無い(どこのメモリ箇所も指していない)と  言う認識でいます。 そこで、仮に下記の処理を行った場合どうなるか試してみました。 ------------------------------------------ stddef.h (void *)0) ------------------------------------------ char *test; test = NULL; printf("[%p]\n", test); // 出力 [00000000] printf("[%s]\n", test); // 出力 [] memcpy(test, "123", 3); // メモリフォルト ------------------------------------------ 予想としては、%sの処理でメモリフォルトとなると思っていたのですが 実際は、メモリフォルトが起こらなかったです。 と言う事は参照先が何かしらあったって事なのでしょうか?

  • ポインタと配列

    次のソースで、結果表示でポインタを使いたいのですが、うまくいきません。1件しか表示されないのです。 ポインタの扱いがおかしいのだと思いますが、どうしたらよいでしょうか? #include <stdio.h> #include <string.h> int search(char key[256],FILE *fp,char *result[256][256]); main(void) { FILE *fp; int rep,n,i; char x[256],key[256],*result[256][256]; printf("検索キーワードを入力してください。\n" "キーワード>"); gets(key); if((fp=fopen("personal.txt","r"))==NULL) { printf("ファイルをオープンできません\n"); exit(1); } printf("=====検索結果=====\n"); n=search(key,fp,result); for(i=0;i<n;i++) { printf("%s\n",result[i]); } printf("検索結果:%d件です。\n",n); fclose(fp); } int search(char key[256],FILE *fp,char *result[256][256]) { int n=0; char *p,word[256],*name; while((p=fgets(word,256,fp))!=NULL) { if(strstr(word,key)!=NULL) { name=strtok(p," "); strcpy(result[n],name); n++; } } return n; } 実行すると、下の警告がでます。 illegal pointer combination(param)

  • ポインタについて

    #include <stdio.h> int main( void ) { intx; printf("x = %p\n", &x); printf("x = %d\n", &x); printf("x = %p\n", x); printf("x = %d\n", x); return 0; } 一応僕が使っている参考書によると printf("x = %p\n", &x); はxのアドレスを表示するようですが 他の三つは何を表示するのでしょうか? よければ詳しい説明をつけてくれるとうれしいです (~が~だから~と表示される)みたいなかんじで お願いします

  • ポインタのポインタの必要性

    書物によるとポインタのポインタの使用例として「ポインタの配列」はポインタを使ってアクセスすることができます。」[*]とありますが、どうしてポインタのポインタが必要なのかがいまいちピンと来ません。 どういう場合なのかを知りたく思っています。 [*]サンプルスクリプト ===================================================== char *mnthp[3] = {/* ポインタの配列の宣言 */ "January", "February", "March" }; char **p1;/* 「ポインタのポインタ」の宣言 */ int i, j; p1=mnthp;/* 「ポインタのポインタ」にポインタの配列 */ /* の先頭番地を設定 */ /***** 例1 *****/ for (i = 0; i < 3; i++) {/* 「ポインタのポインタ」の値を変えずに */ printf("%s\n", *(p1 + i));/* 相対的に文字列を出力 */ } ==> このようなことをしなくとも printf("%s", mnthp[i]); で値を参照出来ると思われる。 ===================================================== [*] http://www9.plala.or.jp/sgwr-t/c/sec10-4.html 宜しくお願い致します。

  • ポインタのポインタ

    こんにちは。 C言語の「ポインタのポインタ」の学習中なのですが、以下のプラグラムがエラーが出てしまします。 if文が間違っていると思うのですが、具体的に何がどう間違っているのがわかりません。 ご教示お願いいたします! #include<stdio.h> int main(void) { int date = 300; int *pdate = NULL; int **ppdate = NULL; printf("dateの値は%d<\n", date); pdate = &date; printf("*pdateの値は%d<\n", *pdate); if(**ppdate = NULL){ printf("**ppdateには何も与えられていません。\n"); } else{ return 0; } ppdate = &pdate; if(**ppdate == 300){ printf("**ppdateの値は%dになりました。正常です。\n", **ppdate); } /*強制終了を避けるためのプログラム*/ int i; scanf("%d", &i); return 0; }

  • ポインタ?

    #include <stdio.h> main() { char s[] = "I love cat and dog."; char c = 'a'; char *p = s; int n = 0; printf("\"%s\"の中から\'%c\'をさがします。\n", s, c); while(*p != '\0') { if(*p == c) { printf("%d番目で発見しました。\n", p - s + 1); ++n; } ++p; } if(n == 0) { printf("1つも見つかりませんでした。\n"); } else printf("全部で%d個見つかりました。\n", n); return 0; } わからないので質問したいのですが、これは「Cの絵本」という、 本に出ているサンプルプログラムです。 わからないところは、 12行目の、printf("%d番目で発見しました。\n", p - s + 1); ところです。その、「p - s」のところが特にわかりません。 ポインタって言うのは、アドレスを格納する変数ですよね? その、pからsを引いても0になるんじゃないかと思って、理解が できません。どうして、このp-sで、cの位置が発見できるのかが 理解できません。最後の+1は配列が0から始まるんで+1にすれば いいのはわかるんですが、p-sでどんなことが起きているかが 理解できなくて。ポインタをちゃんと理解できていないから、 こういった疑問が出てくるんですかね? ほかの参考書も本屋さんに行って見てみようと思っているんですが、 どなたか教えていただけませんか? よろしくお願いします。

  • C言語、配列とポインタとアスタリスクの関係

    ちょっと行き詰まっています。 苦しんで覚えるCで勉強しているのですが、まさに苦しんでいます。 http://9cguide.appspot.com/19-01.html #include <stdio.h> #include <stdlib.h> int main() { int i; int *heap; heap = (int *)malloc(sizeof(int) * 10); if (heap == NULL) exit(0); for (i = 0;i < 10;i++) { heap[i] = i; } printf("%d\n",heap[5]); free(heap); return 0; } int *heap; ここで int ポインタを宣言しています。 heap = (int *)malloc(sizeof(int) * 10); ここでヒープを確保しています。(int *) のキャストも sizeof(int) も理解できました。 for (i = 0;i < 10;i++) { heap[i] = i; } まず1点目の疑問はここです。 変数 heap は「ポインタ変数」です。それでいて配列です。 ポインタ変数は、プログラムの文中で通常の変数として使うときには「*heap」のように先頭にアスタリスクを付けなければならかなったと記憶しています。 アスタリスクなしの「heap」はアドレス格納用の変数ではないでしょうか。 printf("%d\n",heap[5]); そして、その疑問をよそに、この命令が成り立っているようです。 画面上に出される結果は「5」であり、変数「heap」がただの配列として機能しているように見えます。 この printf 次のように書き換えると、エラーが出てコンパイルできませんでした。 書き換え実験1 printf("%p\n",*heap[5]); アスタリスクを付けて、通常の変数として扱い、受ける方も「%d」から「%p」に書き換えてアドレスを表示してみようと思ったのですが、 「「pointer」を付け忘れています。」というエラーが表示されました。 書き換え実験2 printf("%p\n",heap[5]); 受ける方を「%d」からポインタを受ける「%p」にしましたが、変数の方はアスタリスクなしです。 すると、結果はアドレス「00000005」が返ってきました。 (変数にアスタがないのになぜ?) 書き換え実験3 printf("%d\n",*heap[5]); これはもうめちゃくちゃですが、一応やってみました。コンパイルエラーで、 「「pointer」を付け忘れています。」というエラーが表示されました。 つまり、こういうことです。 0:printf("%d\n",heap[5]); //5 1:printf("%p\n",*heap[5]); //エラー 2:printf("%p\n",heap[5]); //00000005 3:printf("%d\n",*heap[5]);//エラー この結果から推測するに、アスタリスクはそもそも付けるとエラーになり、アドレスを表すか、そのアドレスに格納された値を表すかを切り替えるには、単にその変数を受ける「%d」や「%p」を変えるだけ、ということになるのだと思います。 mallocで返ってくるのは、ポインタ変数(の配列)だと思うので、変数のモードを切り替えるためにアスタリスクが必要なのだと思っていましたが、どこかで重大な勘違いをしているようです。 この件について、どなたか教えていただけないでしょうか。

  • ポインタについて

    下記プログラムはどういう動きをしているのでしょうか。 「printf("&a\t--> %p\n", &a );」は、なぜ「&a」なのでしょうか。 aはポインタ変数として宣言してあるのだから、アドレスを表す場合、「a」ではないのでしょうか。 「a = &value;」でvalueのアドレスをaに受け渡していると思うのですが、この場合、1つのアドレスを複数の変数が指しているということでしょうか。 aの値を25に書き換えれば、valueの値も25になるのでしょうか。 では逆にvalueの値を30に書き換えれば、aの値も30になるのでしょうか。 #include <stdio.h> int main() { int value = 10; int *a; printf("&value\t--> %p\n", &value); printf("&a\t--> %p\n", &a ); a = &value; printf("*a\t--> %d\n", *a ); *a = 25; printf("value \t--> %d\n", value ); return 0; }