sizeof(ポインタ)は常に4に等しいですか?


227

例: sizeof(char*)4を返します。、と同様int*long long*、私が試したすべてのものです。これに例外はありますか?


51
なぜこれをマークダウンするのですか?初心者にとって良い質問です。
マーティンヨーク

2
これには別の質問が隠されているのではないかと思います。「sizeofとは何ですか?」または「sizeof <any pointer> == 4なのはなぜですか?4の何がそんなに特別なのですか?」かもしれません。私は正しいですか?

2
まあ、それはあなたのプラットフォームに依存します。ほとんどの実装は、特定のプラットフォーム上のすべての種類のポインターで同じサイズを共有します。
フォアゴン2013年

回答:


194

あなたが得る保証はそれsizeof(char) == 1です。それ以外の保証はありませんsizeof(int *) == sizeof(double *)

実際には、ポインタは、16ビットシステム(サイズがある場合)でサイズ2、32ビットシステムで4、64ビットシステムで8になりますが、特定の値に依存しても何も得られません。サイズ。


96
24ビットシステムでは3バイト。はい、取り組みました。組み込み機器の世界へようこそ。
dwj 2008

30
私は20ビットポインターを備えた16ビットシステムでも作業しました。その場合に返されるsizeofを確認する必要があります...
Maygarden判事2008

5
@monjardin:IIRC、8086はそのようなものでした。16ビットのアドレスと4ビットのセグメントレジスタがありました。通常の "NEAR"ポインターは16ビットであり、 "FAR"として宣言されたポインターは24ビット以上であると思いますが、よくわかりません。
rmeador 2008

18
もう1つの保証は、sizeof(char *)== sizeof(void *)です。これは、それらが同じ表現(オブジェクト[サイズ]と値[値に関連するビットのセット]表現)を持っている必要があるためです
Johannes Schaub-litb

7
質問は例外を求めているため、非静的メンバー関数ポインターは通常のポインターとサイズが異なることが多く、プラットフォーム、タイプなどによっても異なることに注意してください。それ以外は+1です。
John5342 2013年

36

単純なx86 32ビットプラットフォームでも、さまざまなポインターサイズを取得できます。例としてこれを試してください。

struct A {};

struct B : virtual public A {};

struct C {};

struct D : public A, public C {};

int main()
{
    cout << "A:" << sizeof(void (A::*)()) << endl;
    cout << "B:" << sizeof(void (B::*)()) << endl;
    cout << "D:" << sizeof(void (D::*)()) << endl;
}

Visual C ++ 2008では、members-to-member-functionのサイズとして4、12、8が表示されます。

レイモンド・チェンはここでこれについて話しまし


4
メンバー関数へのポインターは本当の痛みです。残念ながら、すべてのコンパイラがDigital Mars C ++コンパイラのように実行するわけではなく、すべてのケースで4を返します。
dalle

gcc 4.72 print all 8 ...これはC ++標準では未定義ですか?
Gob00st

2
@ Gob00st:定義されている唯一のことは、charが1であることです。他の型は、そのコンパイラーに関連するサイズなら何でもかまいません。これらのポインター型の間で一貫性を保つ必要はありません。
Eclipseの

わかりました。そうすれば、gccとVCの実装が異なるのも不思議ではありません。
Gob00st、

5
@Eclipseはい、あります。char<= short <= int <= long <= long long
Cole Johnson

30

既に投稿されたリストのもう1つの例外です。32ビットプラットフォームでは、ポインタは4バイトではなく 6 バイトを使用できます。

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

int main() {
    char far* ptr; // note that this is a far pointer
    printf( "%d\n", sizeof( ptr));
    return EXIT_SUCCESS;
}

このプログラムをOpen Watcomでコンパイルして実行すると、6になります。これは、サポートするfarポインターが32ビットのオフセットと16ビットのセグメント値で構成されるためです。


5
セグメントではなく、セレクター-メモリーアドレスの一部ではなく、LDTまたはGDTのインデックスエントリであり、いくつかのアクセスフラグがあります
Roee Shenberg

1
アドレス空間がフラットなのに、x86にセグメントとオフセットがあるのはなぜですか?
phuclv 2014年

@LưuVĩnhPhúcこれは、ニアポインターの非常に一般的なケースのスペースを節約するためです。
Christopher Creutzig 2014年

1
@ChristopherCreutzigは、PAEのようなアドレス空間の拡張にセグメントが使用されることを意味しますか?
phuclv 2014年

@LưuVĩnhPhúc32ビットのものを組み立てるのは久しぶりです。私が覚えているように見える部分は、あなたが持っているコードの近くを指すポインターのためのスペースを節約できることです。また、32ビットアーキテクチャのすべてがx86に基づいているわけではなく、フラットメモリモデルを使用しているわけではありません。これに関するいくつかのより多くの議論については、例えば、tenouk.com / Bufferoverflowc / Bufferoverflow1a.htmlを参照してください。
Christopher Creutzig 2014年

24

64ビットマシン用にコンパイルしている場合は、8になる可能性があります。


2
これは通常の場合ですが、必ずしもそうではありません。たとえば、ワードサイズが64ビットである64ビットマシンでコンパイルする場合、sizeof(char *)はおそらく1になります。Eclipseやdmityugov書き込み。
Kaz Dragon

@KazDragon 、sizeof(char*)==1? 本気ですか?どういう意味size(char)==1ですか?
アーロンマクデイド2013年

3
@AaronMcDaid私は確かに平均sizeof(char *)をしました。sizeof(char)は常に1ですが、マシンワードが64ビットであり、開発環境がCHAR_BITS = 64のように実装されている場合、ポインターがcharと同じスペースに収まるため、また、1である
カズドラゴン


1
@KazDragon 16ビットワードでバイトアドレス指定のないマシンを構築しています(非常に遅い、先延ばしでない場合)。とにかくCを実行することはできませんが。
user253751

17

技術的に言えば、C標準はsizeof(char)== 1のみを保証し、残りは実装次第です。しかし、最新のx86アーキテクチャ(例:Intel / AMDチップ)では、かなり予測可能です。

16ビット、32ビット、64ビットなどとして説明されているプロセッサを聞いたことがあるでしょう。これは通常、プロセッサが整数にNビットを使用することを意味します。ポインタはメモリアドレスを格納し、メモリアドレスは整数であるため、ポインタに使用されるビット数が効果的にわかります。sizeofは通常バイト単位で測定されるため、32ビットプロセッサ用にコンパイルされたコードはポインタのサイズを4(32ビット/バイトあたり8ビット)と報告し、64ビットプロセッサのコードはポインタのサイズを8と報告します(64ビット/バイトあたり8ビット)。これは、32ビットプロセッサの4 GBのRAMの制限が原因です。各メモリアドレスがバイトに対応している場合、より多くのメモリをアドレス指定するには、32ビットより大きい整数が必要です。


「16ビット、32ビット、64ビットなどのプロセッサーについて聞いたことがあるでしょう。これは通常、プロセッサーが整数としてNビットを使用することを意味します。」-> 64ビットマシンを使用していますが、sizeof(int)は4バイトです。あなたの声明が真実なら、これはどのようにして可能でしょうか?
Sangeeth Saravanaraj 2012

6
@SangeethSaravanaraj:32ビットコードとの下位互換性のために、intを4バイトのままにし、 'long'を指定して8バイトタイプを使用するようにオプトインすることを決定しました。longは、実際にはx86-64のネイティブワードサイズです。これを確認する1つの方法は、通常、コンパイラーが構造体をパディングしてワードアラインメントにすることです(ただし、ワードサイズとアラインメントが無関係のアーキテクチャもあるかもしれません)。そのため、int(32ビット)で構造体を作成するとその上でsizeof()を呼び出します。8に戻れば、64ビットのワードサイズにパディングされていることがわかります。
ジョセフガービン2012

@SangeethSaravanaraj:理論的には、CPUのネイティブワードサイズとコンパイラが「int」を決定するものは任意に異なる場合があることに注意してください。x86-64が登場する前は、「int」がネイティブワードサイズであることが慣例でした。後方互換性を緩和するのは長いです。
Joseph Garvin 2012

説明ありがとう!:)
Sangeeth Saravanaraj 2012

7

ポインターのサイズは、基本的には、ポインターが実装されているシステムのアーキテクチャーに依存します。たとえば、32ビットのポインターのサイズは、64ビットマシンでは4バイト(32ビット)および8バイト(64ビット)です。マシンのビットタイプは、それが持つことができるメモリアドレスにすぎません。32ビットマシンは2^32アドレススペースを持つことができ、64ビットマシンは最大2^64アドレススペースを持つことができます。したがって、ポインタ(メモリの場所を指す変数2^32 for 32 bit and 2^64 for 64 bit)は、マシンが保持するメモリアドレス()のいずれかを指すことができる必要があります。

このため、ポインターのサイズは32ビットマシンでは4バイト、64ビットマシンでは8バイトです。


6

16/32/64ビットの違いに加えて、さらに奇妙なことが発生する可能性があります。

sizeof(int *)が1つの値(おそらく4)になるマシンがありますが、sizeof(char *)の方が大きいマシンがあります。バイトではなくワードを自然にアドレス指定するマシンは、C / C ++標準を適切に実装するために、実際に必要なワードの部分を指定するために文字ポインターを「拡張」する必要があります。

ハードウェアの設計者がバイトアドレス指定の価値を学んだため、これは今では非常に珍しいことです。


4
T90などのCrayベクターマシン用のCコンパイラも同様の処理を行います。ハードウェアアドレスは8バイトで、8バイトワードを指します。void*およびchar*ソフトウェアで処理され、ワー​​ド内に3ビットのオフセットが追加されます。ただし、実際には64ビットのアドレス空間がないため、オフセットは64ビットの上位3ビットに格納されます。語。したがってchar*int*サイズは同じですが、内部表現が異なります。また、ポインタが「実際に」だけであると想定しているコードでは、整数は正しく機能しない可能性があります。
キース・トンプソン、

5

8ビットおよび16ビットのポインターは、ほとんどの薄型マイクロコントローラーで使用されています。つまり、すべての洗濯機、マイクロ冷蔵庫、冷蔵庫、古いテレビ、さらには自動車までです。

これらは実際のプログラミングとは何の関係もないと言えるでしょう。しかし、ここに1つの実際の例があります:1-2バイトのRAMを備えたArduino(チップによって異なります)、2バイトのポインター。

それは最近で、安価で、誰でもアクセスでき、コーディングする価値があります。


4

人々が64ビット(または何でも)システムについて言ったことに加えて、オブジェクトへのポインター以外の種類のポインターがあります。

メンバーへのポインターは、コンパイラーによる実装方法に応じて、ほぼすべてのサイズになる可能性があります。必ずしもすべて同じサイズである必要はありません。PODクラスのメンバーへのポインターを試してから、複数の基底を持つクラスの基本クラスの1つから継承されたメンバーへのポインターを試してください。なんて楽しい。


3

私が覚えていることから、それはメモリアドレスのサイズに基づいています。したがって、32ビットアドレス方式のシステムでは、sizeofは4バイトなので、4を返します。


4
そのような要件はありません。sizeof(unsigned int)== sizeof(signed int)という要件すらありません。intへのポインタのサイズは、定義により、常にsizeof(int *)、charのsizeof(char *)などになります。他の仮定に依存することは、移植性のために悪い考えです。
Mihai Limbășan 2008

あ、そうだ。情報をありがとう。
Will Mc、

1
CHAR_BITが16の場合でも、2を返す可能性があります。sizeof()は、オクテットではなく文字数でカウントされます。
MSalters 2009

5
@Mihai:C ++ではsizeof (unsigned int) == sizeof (signed int)、この要件は3.9.1 / 3にあります。「タイプの符号付き整数標準の各々について、対応する(しかし異なる)標準の符号なし整数型が存在する:unsigned charunsigned short intunsigned intunsigned long int、及びunsigned long long intストレージの同じ量を占有し、対応する符号付き整数型と同じアライメント要件をそれぞれ有します "
ベンフォイト2013

3

一般に、さまざまなプラットフォームでコンパイルすると、sizeof(ほとんどすべて)が変化します。32ビットプラットフォームでは、ポインタは常に同じサイズです。他のプラットフォーム(64ビットが明らかな例です)では、これは変わる可能性があります。



3

Windows 32ビットマシンのTurbo Cコンパイラでは、ポインタとintのサイズは2バイトです。

したがって、ポインタのサイズはコンパイラ固有です。しかし、一般的にほとんどのコンパイラーは、32ビットの4バイトのポインター変数と64ビットのマシンの8バイトのポインター変数をサポートするように実装されています。

したがって、ポインタのサイズはすべてのマシンで同じではありません。


2

ポインタのサイズが4バイトである理由は、32ビットアーキテクチャ用にコンパイルしているためです。FryGuyが指摘したように、64ビットアーキテクチャでは8と表示されます。


2

ではWin64の(CygwinのGCC 5.4) 、のは、以下の例を見てみましょう:

まず、次の構造体をテストします。

struct list_node{
    int a;
    list_node* prev;
    list_node* next;
};

struct test_struc{
    char a, b;
};

テストコードは次のとおりです。

std::cout<<"sizeof(int):            "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*):           "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(double):         "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*):        "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(list_node):      "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*):     "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(test_struc):     "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*):    "<<sizeof(test_struc*)<<std::endl;    

出力は以下のとおりです。

sizeof(int):            4
sizeof(int*):           8

sizeof(double):         8
sizeof(double*):        8

sizeof(list_node):      24
sizeof(list_node*):     8

sizeof(test_struc):     2
sizeof(test_struc*):    8

あなたは64ビットで、ことがわかりますsizeof(pointer)です8


1

ポインターはアドレスのコンテナーにすぎません。32ビットマシンでは、アドレス範囲は32ビットなので、ポインターは常に4バイトになります。64ビットマシンでは、アドレス範囲が64ビットの場合、ポインターは8バイトになります。


1
32ビット・バイトはsizeof(CHAR *)と、32ビットマシン上で1とすることができる
ロバート・ギャンブル

「... 32ビットバイトで」。そのようなものが存在することを知りませんでした...
Ed S.

1
32ビットのアヒルでは、sizeof(char *)はPIを返します
Adriano Varoli Piazza

0

完全性と歴史的な関心のために、64ビットの世界では、主にUnixタイプのシステムとWindowsの間で、LLP64とLP64という名前のlong型とlong long型のサイズに異なるプラットフォーム規則がありました。ILP64という名前の古い規格もint = 64ビット幅にしました。

マイクロソフトは、移植を容易にするために、longlong = 64ビット幅のLLP64を維持しましたが、longは32のままでした。

Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64

ソース:https : //stackoverflow.com/a/384672/48026

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.