2017-07-05 8 views
0

Cで異なるデータ型のサイズを出力するコードを書きました。Cのsizeof演算子の使用

#include<stdio.h> 
int main() 
{ 
    printf("%d", sizeof(int));//size of integer 
    printf("%d", sizeof(float)); 
    printf("%d", sizeof(double)); 
    printf("%d", sizeof(char)); 
} 

これは動作しませんが、私は%ld%dを交換した場合、それが動作します。小さい範囲の数字を印刷するのになぜlong intを取らなければならないのか分かりませんでした。

+0

どのコンパイラ/プラットフォームですか?私はそれがほとんどの場合にうまくいくと思います。 'printf("%d \ n "、sizeof ...);' – i486

+0

"これはうまくいきません"のように '%d 'の後に' \ n'を追加する方が良いです。まさに、どうやって動かないのですか?問題を再現するための手順を示してください。 – jdv

+0

コンパイルエラーが出ていましたが、%zuの回答があります! –

答えて

9

どちらも間違っています%zuタイプsize_tの値を印刷する必要があります。これはsizeofが返すものです。

異なる値が異なるため、一致する必要があります。

あなたのように不一致の動作は未定義なので、何かが起こる可能性があります。

+2

OPがMS Visual Studioを使用していて完全である場合:MS Visual StudioはVS2013の前に '%zu' printf指定子をサポートしていませんでした。 VS2013(例えば、 '_MSC_VER> = 1800')から始まる'%zu'が最終的に利用可能です。 '%zu'が利用できない場合、他の答えのようなキャスティングはオプションになります。 –

3

これは、サイズの不一致によるものです。 %zuを使用するか、%uを使用してunsignedにキャストすると、問題が解決する場合があります。

現在、実装は未定義の動作です。

printf("%u", (unsigned)sizeof(int));//size of integer 
printf("%u", (unsigned)sizeof(float)); 
printf("%u", (unsigned)sizeof(double)); 
printf("%u", (unsigned)sizeof(char)); 

stdoutがバッファリングの新しいラインですので、画面に何かを得るために最後に\nを印刷することを忘れないでください。

+0

'\ n'は良いアイデアですが、\" "4481 \ n"のような出力は余分な間隔に役立ちます。詳細:タイプが一致しないためです。 – chux

+0

申し訳ありませんが、_'stdout'はバッファされた行です。正確ではありません。 stdioは実際に 'ioctl(2)'システムコール(通常は 'isatty(3)'呼び出しの結果として)を記述することによって記述子がttyデバイスに関連付けられているかどうかをチェックし、それが真であればラインバッファリングに切り替わります。それ以外の場合は、完全なバッファリングが行われます。最後の 'printf(3)'の後に、 'stdout'に' fflush(3) 'を呼び出す代わりの方法があります。 –

2

sizeofの返品タイプはsize_tです。スタンダード、

6.5.3.4 The sizeof and _Alignof operators 

5からの両方の演算子の結果の値が定義さ 実装ドFiがあり、その種類(符号なし整数型) size_tの、<stddef.h>(および他のヘッダ)に定義さドFiがあります。

size_tは実装定義です。私のLinuxでは、size_tは__SIZE_TYPE__と定義されています。このトピックでは、詳細hereを見つけることができます。

あなたのケースでは、size_tがintより長い長いものとして実装されています。

+0

OPの 'size_t'はおそらく' unsigned long'ですが、 'long'ではなく' size_t'は 'unsigned'整数型でなければなりません。 –

+0

@DavidBowling、私はそのような小さい値のために印がprintfの動作に影響を与えるとは思わないので、型サイズの問題でそうだと思います。 – alinsoar

+0

小さい値は符号付きおよび符号なし整数として表現できるため、C11§6.5.2.26が適用されます。 'scanf()'は、符号付きまたは符号なしを受け取った場合、「認識」しません。 – chux

0

小さい範囲の数値を印刷するために長いintを使用する理由を理解できませんでした。

size_tは、intがサポートできる値よりもはるかに大きな値を表す可能性があります。私の特定の実装では、最大サイズ値は18446744073709551615であり、は間違いなくintに収まりません。

static long double really_big_array[100000000]; 
... 
printf("sizeof really_big_array = %zu\n", sizeof really_big_array); 
size_t

実装が可能となる最大のオブジェクトの大きさを表現することができなければならない:

sizeofのオペランドがオブジェクト式は括弧型名又はであってもよいことに注意してください。

0

あなたはと言いますが、それは動作しません、しかしあなたはそれが何かを言わない。この予期しない動作のための最も可能性の高い理由は次のとおりです。

  • int値を期待%d変換指定。 sizeof(int)は、タイプがsize_tであり、符号なしであり、多くのプラットフォームではintより大きく、未定義の動作を引き起こします。

printf()のようにvararg関数に異なる型が異なる型で渡されるため、渡された引数の型と変換指定子は一貫していなければなりません。 size_tprintfを渡すと、intが必要です。間違った場所から値が取得され、一致しないと出力が生成されます。

あなたがと言う場合は、%ldと入力すれば動作します。 size_tは、ご使用のプラットフォームでlongと同じサイズになることがありますが、これは偶然であり、64ビットWindowsではsize_tlongより大きいためです。

問題を修正するには、あなたのいずれかを行うことができます

  • は、標準の変換指定子を使用し%zu
  • intとして値をキャスト。

最初のものは正しい修正ですが、一部のCライブラリでは%zuをサポートしていません。特に、VS2013より前のMicrosoft Cランタイムライブラリが最も重要です。したがって、私はより多くのポータブルと明らかに小さいサイズを持っているタイプとオブジェクトのために十分である第2のをお勧めします。

#include <stdio.h> 

int main(void) { 
    printf("%d\n", (int)sizeof(int)); 
    printf("%d\n", (int)sizeof(float)); 
    printf("%d\n", (int)sizeof(double)); 
    printf("%d\n", (int)sizeof(char)); 
    return 0; 
} 

はまた、あなたは出力改行をしないことに注意してください:環境によっては、出力が表示されません改行が出力されるか、fflush(stdout)が呼び出されるまでユーザーを呼び出します。プログラム終了時に出力がコンソールにフラッシュされず、観察された動作を引き起こす可能性もありますが、そのような環境は珍しいことです。意味のある出力の最後に改行を出力することをお勧めします。あなたのケースではそうしないと、すべてのサイズが4481のような一連の数字としてまとまってしまうことがあります。

+0

haha​​haha ...まあ...その後私はまた認めて、彼の方法の私のコメントを離陸する:) –

関連する問題