8

重複の可能性:
C では NULL は常にゼロですか?

C 標準では、 について次のように規定されていますcalloc()

calloc 関数は、それぞれのサイズが size である nmemb オブジェクトの配列にスペースを割り当てます。スペースは全ビット 0 に初期化されます。

すべてのビットがゼロに関連する次の注意事項があります。

これは、浮動小数点ゼロまたはヌル ポインター定数の表現と同じである必要はないことに注意してください。

テストプログラム:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
    char** list = calloc(10, sizeof(*list));
    int i;
    for (i = 0; i < 10; i++)
    {
        printf("%p is-null=%d\n", list[i], NULL == list[i]);
    }
    free(list);

    return 0;
}

このプログラムをビルドし、次のコンパイラで実行しました。

  • VC7、VC8、VC9、VC10
  • gcc v4.1.2、gcc v4.3.4
  • フォルテ5.8、フォルテ5.10

すべての場合において、すべてのビット 0NULLポインターです (テスト プログラムで間違いを犯した場合を除きます)。

ポインターが C 標準ですべてのビットがゼロNULLになることが保証されていない理由は何ですか? 好奇心から、すべてのビット 0がポインターではないコンパイラーはありますか?NULL

4

2 に答える 2

10

com.lang.c FAQは、質問 5.16でこれに答えており、そこではなぜこれが起こるのかを説明し、質問 5.17ではゼロ以外の実際のマシンの例を示していますNULL。比較的「一般的な」ケースは、アドレス 0 が有効であるため、別の無効なアドレスが に選択されNULLます。より難解な例は、Symbolics Lisp Machine です。これには、私たちが知っているようなポインターさえありません。

したがって、適切なコンパイラを選択することは問題ではありません。仮想メモリの有無にかかわらず、最新のバイトアドレス指定可能なシステムでNULLは、アドレス 0 ではないポインターに遭遇する可能性はほとんどありません。

C 標準は、まったく奇妙なハードウェアに対応するように注意深く設計されており、これはその結果の 1 つにすぎません。同じ線に沿った別の奇妙な落とし穴は、それが可能であるということsizeof(void *) != sizeof(int *)ですが、バイトアドレス指定可能なアーキテクチャでそれが起こることは決してありません.

于 2012-11-06T12:59:34.450 に答える
4

はい、NULLポインターの内部表現がすべてビットゼロではない実装がいくつかあります (それらのいくつかはエキゾチックです)。C FAQのこのセクションは非常に興味深いものです (特にこれらのもの : 12 )。

于 2012-11-06T12:59:22.090 に答える