1

私が今まで読んだほとんどのコードはint、標準のエラー処理(関数などからの戻り値)にを使用しています。しかし、willコンパイラを使用することで得られるメリットがあるかどうか疑問に思っていますuint_8-読み取り:ほとんどのアーキテクチャのほとんどのCコンパイラ-イミディエートアドレスモードを使用して命令を生成します-つまり、1バイトの整数を命令に埋め込みます?私が考えている重要な命令は、戻り型としてuint_8を使用して、関数が戻った後の比較です。

1バイト型を導入するとアライメントの問題が発生するため、私は間違って考えている可能性があります-コンパイルが4バイトにパックするようにコンパイルするのはおそらく完全に正しい理由であり、これがおそらく誰もがintを使用する理由です-そしてこれはヒープではなくスタック関連の問題であるため、実際のオーバーヘッドはありません。

正しいことをすることが私が考えていることです。しかし、議論のために、これはインテリジェントウォッチに人気のある安価なマイクロプロセッサであり、1kのメモリで構成されていますが、命令セットに異なるアドレッシングモードがあるとしましょう:D

ディスカッション(x86)を少し専門化するためのもう1つの質問は、次のとおりです。

uint_32 x=func(); x==1;

uint_8 x=func(); x==1;

同じタイプ?または、2番目のケースでは、コンパイラは8バイトのリテラルを生成します。その場合、それを使用して、リテラルを即値として、返されたintをレジスタ参照として持つ比較命令を生成できます。CMP命令タイプを参照してください。

x86命令セットのもう1つの参照。

4

4 に答える 4

4

次のコードに対して、ある特定のコンパイラが行うことは次のとおりです。

extern int foo(void) ;
void bar(void)
{
        if(foo() == 31) { //error code 31
                do_something();
        } else {
                do_somehing_else();
        }
}

   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   e8 fc ff ff ff          call   7 <bar+0x7>
   b:   83 f8 1f                cmp    $0x1f,%eax
   e:   74 08                   je     18 <bar+0x18>
  10:   c9                      leave
  11:   e9 fc ff ff ff          jmp    12 <bar+0x12>
  16:   89 f6                   mov    %esi,%esi
  18:   c9                      leave
  19:   e9 fc ff ff ff          jmp    1a <bar+0x1a>

cmpの3バイト命令。foo()がcharを返す場合、b:3c 1f cmp $ 0x1f、%alを取得します。

ただし、効率を求めている場合。%a1の内容の比較が%eaxとの比較よりも速いと思い込まないでください

于 2009-12-02T18:10:17.403 に答える
3

特定のアーキテクチャでは、異なる整数タイプ間で速度の差が非常に小さい場合があります。ただし、これに依存することはできません。別のハードウェアに移動すると変更される可能性があり、新しいハードウェアにアップグレードすると実行速度が低下する可能性があります。

そして、あなたが与えている例でx86について話すなら、あなたは誤った仮定をします:即時はタイプである必要がありますuint8_t

実際、命令に埋め込まれている8ビットのイミディエートはタイプであり、C表記: 、、、およびで、バイト、ワード、dword 、int8_tおよびqwordで使用できます。charshortintlong long

したがって、このアーキテクチャでは、コードサイズも実行速度もまったくメリットがありません。

于 2009-12-02T14:12:31.567 に答える
3

計算にはint型またはunsignedint型を使用する必要があります。化合物(構造体/配列)にのみ小さい型を使用します。その理由は、intは通常、プロセッサにとって「最も自然な」整数型として定義されており、他のすべての派生型では、正しく機能するために処理が必要になる場合があるためです。私たちのプロジェクトでは、Solaris for SPARCでgccを使用してコンパイルしましたが、8ビットと16ビットの変数にアクセスするケースでコードに命令が追加されました。メモリから小さいタイプをロードするときは、レジスタの上部が正しく設定されていることを確認する必要がありました(符号付きタイプの場合は符号拡張、符号なしの場合は0)。これにより、コードが長くなり、レジスタへの圧力が高まり、他の最適化が悪化しました。

具体的な例があります。

構造体の2つの変数をuint8_tとして宣言し、そのコードをSparcAsmで取得しました。

    if(p->BQ > p->AQ)

で翻訳されました

ldub    [%l1+165], %o5  ! <variable>.BQ,
ldub    [%l1+166], %g5  ! <variable>.AQ,
and     %o5, 0xff, %g4  ! <variable>.BQ, <variable>.BQ
and     %g5, 0xff, %l0  ! <variable>.AQ, <variable>.AQ
cmp     %g4, %l0    ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL586  !

そしてここで、2つの変数をuint_tとして宣言したときに得たもの

lduw    [%l1+168], %g1  ! <variable>.BQ,
lduw    [%l1+172], %g4  ! <variable>.AQ,
cmp     %g1, %g4    ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL587  !

他のもののために2つの算術演算が少なく、2つのレジスタが多い

于 2009-12-02T17:11:45.533 に答える
1

プロセッサは通常、Cでは「int」である自然なレジスタサイズで動作するのが好きです。

例外はありますが、存在しない問題について考えすぎています。

于 2009-12-02T13:36:51.717 に答える