2009-09-10 5 views
29

私はプログラムによって使用されたメモリの量を印刷するいくつかのコードを持っています。行は次のようになります。sizeof 32 for 64プラットフォームのprintf:プラットフォームに依存しないフォーマットコードを処理するにはどうすればよいですか?

printf("The about of RAM used is %u", anIntVariable*sizeof(double)); 

ここで、anIntVariableは、double配列の要素数のint変数です。とにかく、32ビットシステムでは何の問題もありませんでしたが、64ビットシステムでは、符号なしのlong整数に "%u"を使用することに関するコンパイラの警告が出ます。フォーマットコードとして "%lu"を使用すると、64ビットで問題が修正されますが、タイプが符号なしintに戻っているため、コンパイラは32ビットでエラーを発生させます。私は、実際にはsizeof(double)が32対64ビットシステムで異なる値を返すことに気付きました。私はにいくつかのウェブページのガイドを見つけました 32ビットから64ビットにコードを変換しますが、私はむしろ前後に変換する代わりに両方で動作するコードを持っています。

この行をプラットフォームに依存しない方法で書くにはどうすればよいですか?私はプリプロセッサディレクティブを使用してそれを行うことができる多くの方法を知っていますが、それはハックのようです。確かに私が実現していないエレガントな方法があります。

+2

良い質問。 – strager

+0

本当にいい質問です。 http://バイトを見てください。com/topic/c/answers/506972-64-bit-portability-size_t-printf-format-strings – adatapost

+1

参照:http://stackoverflow.com/questions/1401526/use-printf-to-display-offt-nlinkt- sizet-and-others –

答えて

20

ポータブルprintf識別子はインクルードファイルinttypes.hで提供されています。

このインクルードファイルには、特定のランタイム用の多くの移植可能な識別子があります。たとえば、「PR intf Iデンティファイヤuを意味するPRIuPTRがポインタのサイズまでのサイズであることを意味します。

あなたの例では、次のようになりますGCC 4.3で64ビットLinux上

printf("The amount of RAM used is %" PRIuPTR, anIntVariable*sizeof(double)); 

結果(int anIntVariable = 1):

$ gcc test.c -m32 -o test && ./test 
The amount of RAM used is 8 
$ gcc test.c -o test && ./test 
The amount of RAM used is 8 

完全性期すために、その接頭辞SCNですあまりにもscanf関数の識別子があり、 。

+1

今回はテスト済みのコードで私の答えを編集しました:) – LiraNuna

+0

このアイデアは私の質問に答えるようです。私は何年もの間Cでプログラミングしてきましたが、私の問題は通常実用的であり、移植性のようなものはまれです。このような単純な状況でアーキテクチャがどのように役割を果たしているか、私はやや驚いています。ありがとう、リラとトーマスあまりにも、まともな解決策を持っていたが、これは完全な答えと思われる。 –

+1

これはまだポータブルではありません。 'sizeof(size_t)== sizeof(uintptr_t)'と仮定しますが、これは保証されません。 'PRIuPTR'は「ポインタのサイズまで」は動作しません。 **正確には 'uintptr_t'幅の整数型でのみ動作します。 –

13

sizeofの戻り値はsize_tです。 C99準拠のコンパイラを使用している場合は、 %zd %zuのように見えます。

D'oh:%zu(無署名)です。ありがとう、オニ。

+1

で ''%zu "'と 'ssize_t'のために' '%zd" 'で定義されている可能性があります、 – ony

+0

@yyええ、私は'%zu 'ここに(私の答えを編集した)。コードが符号付き 'int'に符号なし' size_t'を掛けているので、少し混乱します。その結果は符号なし整数型でなければなりません。 – wds

7

まず、 "%"指定子を実際の印刷するデータタイプと一致させる必要があります。 sizeofは、データタイプsize_tを返します。また、 "%d"指定子を使用してフロートを印刷しないように、 "%u"または "%d"でsize_tを印刷しないでください。またはsize_tを意味するものではありません。

新しいコンパイラ( "%z"とPRIu32)でこれを処理する良い方法がいくつかありましたが、私たちがこれを行う方法は単純にsize_tをunsigned longにキャストし、 「%のLU」:

printf("The amount of RAM used is %lu", (unsigned long)(anIntVariable*sizeof(double))); 

これは、size_tのは、長いよりも広いですが、私はどのようなシステムを知らない、と私は標準がそれを許可する場合であってもよく分からないシステムでは動作しません。

+0

トーマス。 (size_t)を実行するとanIntVariableの型を継承すると仮定していたのですが、そうではありません。問題を解決するにはどうすればよいですか?私はまだ質問に関連している(size_t)を含む式の型宣伝の振る舞いを見つけていません。 –

+3

win64はsize_tがより広いシステムです長いより。 –

関連する問題