• ベストアンサー

sizeof(long), sizeof(short)   (処理系依存と言うけれど・・・)

  数値(整数)型の定義サイズについて、質問です。 ANSIの規格では、 sizeof(short) ≦ sizeof(int) ≦ sizeof(long) としか定義されていないので、実際にこれらの型が取る大きさは処理系依存だ、と聞きます。 しかし、VC++、BCCなど、知名度の高いコンパイラでは、いずれも、 sizeof(short) → 2 sizeof(int) → 2 sizeof(long) → 4 となっているようです。(手元にないので、gccでは確認していませんが・・・) 実際のところ、上記のサイズにならない処理系は実在するのでしょうか? 何故こんな質問をするのかというと、あるテキスト(事情があって、書名等の情報は出せないのですが)に > 次の sizeof 演算子の返す値として正しいものはどれですか。 > > long hoge[32]; > sizeof(hoge); > ------------------------------------------------------ > A. 32 > B. 64 > C. 128 > D. 256 > E. 512 という問題が掲載されており、解説が、 > 正解は C 。 > > long 型は 4 バイトで構成されるので、32 個の要素がある配列では、 128 バイトになります。 となっていたのです。(short型のサイズを問う類題あり) 特定の処理系が前提条件とされていないので、適切な設問、解説とは思えないのですが、誤りと断言できるほどの自信がないため、作者に指摘すべきか否か、迷っています。 sizeof(short) → 2、sizeof(long) → 4 にならない処理系が実在しなければ、規格の定義上は正しくなくても、実務上は誤りとは言えないような気もしますが、どうでしょうか? コメントをお待ちしております。  

noname#4564
noname#4564

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

  • ベストアンサー
回答No.1

64ビットマシン向けの商用UNIXのほとんどでは、 sizeof(long)は 8 となっているはずです。(LP64モデルを採用) ちなみに、 Win64では 4 のままです。(LLP64モデルを採用) さらに重箱の隅をつつくようで申し訳ないですが、IA32向けのVC++や、BCCでは、sizeof(int)は 2 ではなく 4 を返しますね。ご確認を。 参考まで。

noname#4564
質問者

お礼

コメントありがとうございます。 > 64ビットマシン向けの商用UNIXのほとんどでは、 > sizeof(long)は 8 > となっているはずです。(LP64モデルを採用) ということは、 > 規格の定義上は正しくなくても、実務上は誤りとは言えないような気もします はとんでもない話で、この内容では、テキスト(教材)としての品質に大いに問題がありそうですね。 クレーム(修正要求)を付けた方がいいかな? > IA32向けのVC++や、BCCでは、sizeof(int)は 2 ではなく 4 を返します おっしゃる通りです。 ご指摘ありがとうございます。  

その他の回答 (3)

  • ryuta_mo
  • ベストアンサー率30% (109/354)
回答No.4

学校で char=1Byte int=2Byte long=4Byte short型なんて一言も触れないと言う授業やってます。 int型は大体CPUの通常の整数演算の型に合わせることが多いです。 VC++6で確認したら sizeof(char)=1 sizeof(short)=2 sizeof(int)=4 sizeof(long)=4 sizeof(hoge)=128 という結果が出ました。 Windows95以降は32BitCPUです。 質問にはint=2と書いてありますがそうではないようです。 char,short,longが1,2,4Byteでない処理系は聞いたことありませんが(下の回答見てるとあるようですが)intは昔は2Byte今は4Byteが多いようです。 学校で使われてる教科書はint=-32768~32767なんて書いてあるから2Byteでしょう。 しかも処理系によって換わるなんて一言も書いてありません。 C言語のint型は2Byteみたいに書いてます。 おそらくほとんどの処理系が16Bitだったころに編集した教科書を今でもそのまま使ってるのでしょう。 このような教科書を作るのも問題だしこのような教科書を使ってそのまま授業やってint=2Byteという間違った知識を教えてる学校も問題だと思います。

noname#4564
質問者

お礼

  結局、この件は、内容の不備として作者に連絡し、修正してもらうことにしました。 コメントを頂いた皆様、ありがとうございました。m(_ _)m  

noname#4564
質問者

補足

  > このような教科書を作るのも問題だしこのような教科書を使ってそのまま授業やってint = 2Byteという間違った知識を教えてる学校も問題だと思います。 コメントありがとうございます。 一生VBしか使わないなら、その認識でもOKですが。(^-^; (あっ、VB6.0 → VB.NET でint = 4Byte に変わるからダメだわ(-_-;)  

  • shige_70
  • ベストアンサー率17% (168/946)
回答No.3

やはり、そのテキストの記述は間違っているとしか思えません。 そうならない処理系がいまは実在しなくても将来的には存在するでしょうし、C言語の仕様でサイズが決まっていない以上、正しいと言うことは絶対にできません。 絶対的なサイズとしては、char型は1バイト、と言うことしか決められていません。

noname#4564
質問者

お礼

  > やはり、そのテキストの記述は間違っているとしか思えません。 コメントありがとうございます。 良質な解説書では、型のサイズの問題に加え、ハードウェアアーキテクチャ(Intel系/モトローラ系)によるエンディアンの相違についても言及されている場合が多いと思うのですが、問題の書籍では、移植性や可搬性への配慮が欠けているような気がします。  

  • V-bravo-U
  • ベストアンサー率51% (155/301)
回答No.2

 現在のC言語においてはhiroyapapaのおっしゃるとおりlong型が8バイト体型 になっているコンパイラは実在します。私が仕事で使っているのも8バイト体型です。  で、質問者は「long型32個の配列による容量は128バイトは間違いである可能性もある」 ということを読み取りましたが、私の見解では「まぁ、正しいんじゃないの?」と 読み取っています。  なぜなら、質問者がお使いの書籍の書版がいつなのかが明記されていないため、 4年あたりくらい前に初めて作られた書籍ならともかく、さらに古くから作られている 本と考えるならlong型が8バイト使うものは当時としてはあまり存在しない、すなわち long型は4バイトであると決めうちしている時代であったため、問題として適切と判断されるのです。 #「5年くらい前にはすでにlongは8バイト体型になっているものがあるのを知ってるぞ」なんて  つっこみはとりあえずなしにして下さい。少なくても自分は3年前あたりからlong8バイト  体型でコンパイルされるものがあるのを初めて知りました。(^^;  あと、実際問題として、いまだにlong=4バイトとして広く使われている(≒知名度が高い) ということもあります。これは質問者も明記されていますよね。実務上の云々とありますが、 学習で使われているコンパイラがlong=4バイト仕様なら少なくても現段階においては 実務上問題ないのではないでしょうか。質問者がlong型=8バイト仕様をご存知なら コンパイル環境が変わったときにコンパイラの仕様を調べるいうことでいかがでしょう。 もっとも、今現在使用しているコンパイル環境がlong型=8バイト仕様で教科書が4バイト仕様 というのは大問題ではありますが・・・。  もしよろしければお使いの本の初版と改訂日を確認の上、本の冒頭にある前書きあたりに あるコンパイル環境を調べてみて下さい。改訂が古ければ書籍自体の間違いに当たりませんし、 たいていは前書きに「前提」が書かれているものと思われます。

noname#4564
質問者

お礼

  コメントありがとうございます。 >  なぜなら、質問者がお使いの書籍の書版がいつなのかが明記されていない 残念ながら、その情報も開示致しかねます。m(_ _)m > 実際問題として、いまだにlong=4バイトとして広く使われている おっしゃる通りですが、現実にlongが8バイトである処理系が存在するとのことですので、やはり教材としては不適切かと思います。 > 前書きに「前提」が書かれているものと思われます。 前書きに前提条件を明示する執筆者なら、この設問で出題するとは思えません。  

関連するQ&A

  • (Mac) sizeof演算子のコンパイル

    現在MacBookAirにて入門書を参考にC言語を学んでいます。 その中で、 #include <stdio.h> int main(void) { int a = 1; printf("short int型のサイズは%dバイトです。\n", sizeof(short int)); printf("変数aのサイズは%dバイトです。\n", sizeof(a)); return 0; } と入力しコンパイルすると sample21.c:7: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int’ sample21.c:8: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int’ と表示されコンパイルすることができません。 なんども見直してコードに間違いはないと思いますが、原因が解りません。 他のコードは問題なくコンパイルできます。 この先、sizeof演算子を使って値を求めなければならない章があり、非常に困っています。 どなたか解決策を教えてください。お願いします。

  • 引数が配列のときの関数内でのsizeofについて

    こんにちは. Cを勉強している最中に疑問にあったことを質問させていただきます.以下のプログラムで配列myarrayの中の最大のメンバーを見つけるプログラムです.コメントアウトしてある //int ary_size = sizeof(myarray)/4; をグローバル変数で定義するとうまく最大の数を見つけてくれるのですが, 関数の中で int ary_size = sizeof(ary)/4; と定義するとうまくいきません.そこで,以下の printf("The size of the ary is %d\n",ary_size); という表示を追加したところ,ary_size = 1となっていることが分かりました. なぜそうなるのでしょう?関数の引数はint ary[]の配列なので,sizeof(ary)でaryがメモリ中で占めるバイト数が得られるんじゃないんですかね?ちなみに私の環境ではsizeof(int)は4バイトなので int ary_size = sizeof(ary)/4; と割る4で配列のメンバーの数を求めています. 初心者の質問ですみませんがよろしくお願いします. #include <stdio.h> #include <Windows.h> int myarray[] = {1,2,3,4,5,6,7,2}; int FindMax(int ary[]); //int ary_size = sizeof(myarray)/4; int main() { int max; max = FindMax(myarray); printf("The maximum value is %d\n",max); Sleep(2000); return(0); } int FindMax(int ary[]) { int ary_size = sizeof(ary)/4; int i; int max; max = ary[0]; for(i=1;i<ary_size;i++) { if(ary[i]>max) { max = ary[i]; } } printf("The size of the ary is %d\n",ary_size); return(max); }

  • C/C++の型について

    Windows2000で、VC++6で型のサイズを調べると、以下のとおりでした。 int 4バイト long 4バイト long int 4バイト 環境はWindows2000, CPUはCeleron1200Mhzです。 環境やコンパイラによって型のサイズや呼び方も変わるのでしょうか? VisualBasic6用のDLLをVCで作成した記憶があるのですが、そのときは VB6のInteger型が2バイトだったので C(Ver7.0?????)側も2バイトだったと思います。 今VB6のInteger型にあわせる場合はC側ではshortでないとおかしくなるのでしょうか? 私はブランクがあり、そのあたりの事情がよくわかっていません。 あるサイトのページを見ると intが2バイトで、 long intは同じ4バイトで long long intという型もありました。VC6++では long long intは無いようです。 http://seclan.dll.jp/c99d/c99d05.htm VC2005++やGCCでは8バイトの型はあるのでしょうか?

  • ポインタのサイズ

    ポインタのサイズがintと同じになるのは知っているのですが、 以下のコードの場合、 typedef struct hoge{ char buf1[8]; char buf2[16]; }HOGE; void test_func(HOGE *pHoge) { printf("型[%d],実際[%d]\r\n", sizeof(HOGE), sizeof(*pHoge)); memset(pHoge, 0x00, sizeof(*pHoge)); } 正しくサイズが取得できるのですが、 この使い方はC99の仕様的には正しいのでしょうか? よろしくお願いします。

  • HTKのヘッダについて

    HTKというツールキッドを使用しています。 HTKでは任意のデータを使ってHMMの学習ができるのですが、そのときにデータファイルに12バイトのヘッダを付加する必要があります。 この処理をc言語のプログラムでやろうとしているのですが、うまくいきません。 ヘッダは、long型long型short int型short int型という4つの情報で構成されていて、そのあとにfloat型のデータが続いています。 使用しているプログラムの一部は以下のようになっています。 out = fopen("outfile", "wb"); fwrite(&head1,sizeof(long),1,out); fwrite(&head2,sizeof(long),1,out); fwrite(&head3,sizeof(short),1,out); fwrite(&head4,sizeof(short),1,out); fwrite(data, sizeof(float), num, out); //data[]がデータ fclose(out); このプログラムで書き出したファイルでHTKのHInitを実行すると「ヘッダが読み込めない」というエラーがでてしまいます。 任意のデータをHTKフォーマットにするにはどうすればいいのでしょうか?教えてください。よろしくお願いします。

  • C言語signed long long型の演算

    C言語で以下の演算を行った場合、変数bに格納される値が-1(0xFFFFFFFFFFFFFFFF)になることを期待しておりましたが、参照すると4294967295(0x00000000FFFFFFFF)となってしまいます。 unsigned int a = 1; signed long long b; b = a * (-1); 32bit、64bitのUNIX(Solaris)マシンでそれぞれ確認しましたが、どちらも同じ結果となりました。 変数aの型宣言をsigned intにすると変数bが-1(0xFFFFFFFFFFFFFFFF)になることは確認したのですが、unsigned intだとなぜこのような演算結果となるのかが分かりません。 ※8バイト整数に格納する際に先頭4バイトがなぜ0xFFFFFFFFで補完されないのか? ちなみに変数bの型宣言をsigned long intにすると32bitマシンでは-1となりましたが、64bitマシンでは4294967295となってしまいます。 これは32bitUNIXマシンではsigned long intは4バイト領域であるため-1(0xFFFFFFFF)となり、64bitUNIXマシンでは8バイト領域のため前述と同じ結果になるのだと考えますが、なぜ8バイト整数を使用するとこのような演算が行われるのかが分からないので、演算順序や型変換の優先順位がどのように行われいるのか説明できる方教えてください。

  • C言語の型による処理速度の違い

    short int型よりint型。float型よりdouble型の方が 扱えるサイズは広いにも関わらず処理速度が速いと 聞いたのですが、それは本当でしょうか? もしそうならなぜそうなるのでしょう? (一度BCCでfloatとdoubleの処理速度を計ったらfloatの 方が少し早かったですが・・) 高速なプログラムを書く必要の出たときのために型に よる処理速度を教えてください。

  • 標準Cでのオブジェクト(変数)の定義について

    標準Cのオブジェクト(変数)の定義に「その内容によって、値を表現することができる実行環境中の記憶域の領域。ビットフィールド以外のオブジェクトは、連続する1つ以上のバイトからなる。そのバイトの個数、順序および符号化規則は、明示的に規定するかまたは処理系定義とする。 オブジェクトを参照する場合、オブジェクトは、特定の型をもっていると解釈してもよい。」とありますが、具体的に何を指しているのかが解りません。以下のように疑問点をまとめました。 1、「そのバイトの個数、順序および符号化規則は、明示的に規定するかまたは処理系定義とする。」    Int型 long型 double型等を例に取ると、「処理系定義」はそのバイト数が4バイト8バイトと考えられますが、「明示的に規定する」とは、Int型 long型 double型等で具体的にどのような定義を指しているのでしょうか? 2、「オブジェクトを参照する場合、オブジェクトは、特定の型をもっていると解釈してもよい。」とは、具体的に一体何を言いたいのか解りかねます。「参照」とは何を指しているのか?ポインタを指しているのか、「ポインタを指している」としたならなぜそれをここに書き加える必要があるのか?それとも、もっと一般的な事をいっているのか?もしもっと一般的な事を言っているならそれは何なのか? 宜しく願います。

  • intやshortやcharの変数確保時間

    for文などでよく一時変数に for ( int i=0; ・・・ とか for ( short s=0; ・・・ とか for ( char i=0; ・・・ みたいに整数型の変数が使われます。 確か変数の表せる範囲は long>int>short>char だったと思うのですが、変数を確保する時間やメモリサイズに違いはあるのでしょうか? たとえばlong型変数を10万個確保する時間とintとかshortとかcharのそれ とは違いがあるのかなぁと疑問に思いました。

  • MicroC コンパイラ 変数宣言

    MicroC コンパイラ 変数宣言について質問です BYTE tmp1; WORD tmp2; なる定義があったとして 変数型範囲はどの範囲になるのでしょう 下記の定義は見つかったのですが 上記は分かりません 変数型 バイト数 範囲 (unsigned) char 1 0 .. 255 signed char 1 - 128 .. 127 (signed) short (int) 1 - 128 .. 127 unsigned short (int) 1 0 .. 255 (signed) int 2 -32768 .. 32767 unsigned (int) 2 0 .. 65535 (signed) long (int) 4 -2147483648 .. 2147483647 unsigned long (int) 4 0 .. 4294967295 float 4 ±1.17549435082 * 10-38 .. ±6.80564774407 * 1038 double 4 ±1.17549435082 * 10-38 .. ±6.80564774407 * 1038 long double 4 ±1.17549435082 * 10-38 .. ±6.80564774407 * 1038