質問

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

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

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

議論 (x86) を少し特殊化した別の質問は次のとおりです。は次のリテラルです:

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

そして

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

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

x86 命令セットに関する別のリファレンス。

役に立ちましたか?

解決

ここに1つの特定のコンパイラは、次のコードのために何をするかです。

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は()文字を返す場合、我々が得ます  B:図3c 1F CMP $から0x1f、%のAl

あなたがが、効率を探しているなら。 %A1のものを比較すると、%eaxに

と比較してより高速であると仮定しないでください。

他のヒント

特定のアーキテクチャ上の異なる整数型の間に非常に小さな速度差があるかもしれません。しかし、あなたは、あなたが別のハードウェアに移動した場合、それは変更される可能性があり、それに頼ることはできない、とあなたは、新しいハードウェアにアップグレードする場合はそれも遅くなることがあります。

そして、あなたは、あなたが与えている例でのx86について話す場合は、falseを仮定します:タイプuint8_tであることが当面のニーズを。

は、実際の命令に埋め込まれた8ビットの即値は、C表記で、タイプint8_tのものであり、バイト、ワード、ダブルワード及びqwordsで使用することができる:charshortint及びlong long

だから、このアーキテクチャでは何も全く利益、コードサイズや実行速度のいずれもないでしょう。

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

具体的な例があります。

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

    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 つ増えます

プロセッサは、一般的にCで「int型」である彼らの自然なレジスタのサイズ、で作業するのが好き。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top