16

最近まで、私はほとんどのシステム実装者/ベンダーによるint、64ビットマシンでもプレーンな32ビットを維持するという決定を一種の便利な疣贅と考えていました。最新のC99固定サイズ型(int32_tおよびuint32_tなど)では、8、16、32、および64の各サイズの標準整数型が必要になることはほとんどなくなり、int64ビットにすることもできるようです。 。

ただし、Cのプレーンのサイズの最大の実際の結果は、intCが本質的に型よりも小さい演算を持たないという事実から生じintます。特に、intが32ビットより大きい場合、uint32_t値の算術演算の結果は型signed intになり、かなり不安定になります。

intこれは、実際の実装で32ビットに永続的に固定するのに十分な理由ですか?私はそう言うことに傾いています。32ビットを超えるuint32_tと壊れてしまうような、膨大な種類の用途があるように思われます。intにキャストバックしない限り、単項マイナスまたはビット単位の補数演算子を適用しても危険になりますuint32_t

もちろん、同じ問題が現在の実装にも当てはまりますuint16_tuint8_t、誰もがそれらを「より小さいint」タイプとして扱うことに気づいていて、慣れているようです。

4

8 に答える 8

7

あなたが言うように、私は昇進のルールが本当にキラーだと思います。uint32_tその後、昇格しint、突然、ほとんどすべての人が署名されていないことを期待する算術に署名したことになります。

これは、算術演算を実行してに割り当てる場所ではほとんど隠されていますuint32_t。しかし、定数と比較する場所では致命的となる可能性があります。明示的なキャストを行わずにそのような比較に依存するコードが合理的かどうかはわかりません。のようなキャスト定数(uint32_t)1は非常に面倒になる可能性があります。個人的には、少なくとも常にU符号なしにしたい定数の接尾辞を使用しますが、これはすでに私が望むほど読みやすくはありません。

また、uint32_tetcが存在することを保証するものではないことにも注意してください。でもないuint8_t。その施行はPOSIXからの拡張です。したがって、その意味で、言語としてのCは、その動きをすることができるとはほど遠いです。

于 2010-12-30T08:38:34.123 に答える
5

「リーズナブルなコード」...

ええと...開発についてのことは、あなたがそれを書いて修正し、それからそれが機能するということです...そしてあなたはやめます!

そして、多分あなたはたくさん火傷を負ったので、あなたは特定の機能の安全な範囲内に十分にとどまります、そして多分あなたはその特定の方法で火傷を負わなかったのであなたは親切な何かに頼っていることに気づいていません-変化の。

または、バグに依存している場合でも。

古いMac68000コンパイラでは、intは16ビット、longは32でした。しかし、それでも、ほとんどの現存するCコードはintが32であると想定していたため、ニュースグループで見つけた一般的なコードは機能しませんでした。(ああ、Macにはprintfがありませんでしたが、私は逸脱します。)

だから、私が得ているのは、はい、あなたが何かを変えると、いくつかのものが壊れます。

于 2010-12-30T01:33:04.320 に答える
3

最新のC99固定サイズタイプ(int32_tやuint32_tなど)では、各サイズ8、16、32、および64の標準整数型が必要になることはほとんどありません。

C99には、固定サイズのタイプではなく、固定サイズのtypeDEFがあります。ネイティブC整数型は、引き続きchar、、、、、およびです。それらはまだ関連しています。shortintlonglong long

ILP64の問題は、C型とC99型定義の間に大きな不一致があることです。

  • int8_t = char
  • int16_t=短い
  • int32_t=非標準タイプ
  • int64_t = int、long、またはlong long

64ビットプログラミングモデルから:なぜLP64なのか?:

残念ながら、ILP64モデルは、32ビットデータ型を記述するための自然な方法を提供しておらず、その __int32ような型を記述するなど、移植性のない構造に頼らなければなりません。これは、構造なしで32ビットと64ビットの両方のプラットフォームで実行できるコードを作成する際に実際的な問題を引き起こす可能性があります #ifdef。アプリケーションによって入力情報が外部に表示されなかった場合でも、データセットへの投資を維持しながら、このような変更を行うことなく大量のコードをLP64モデルに移植することが可能になりました。

于 2010-12-30T01:54:53.240 に答える
3

DECAlphaおよびOSF/1 Unixは、Unixの最初の64ビットバージョンの1つであり、64ビット整数(ILP64アーキテクチャ)を使用していました(つまりintlongポインターはすべて64ビット量でした)。それは多くの問題を引き起こしました。

私が言及していない問題の1つは、64ビットを使用しているint場合、どのサイズに使用するのshortかということです。16ビット(従来の、何も変更しないアプローチ)と32ビット(急進的な'アプローチのshort半分の長さである必要があります)の両方で、intいくつかの問題が発生します。

C99<stdint.h><inttypes.h>ヘッダーを使用すると、固定サイズの整数にコーディングできます。36ビットまたは60ビットの整数(少なくとも準正規)のマシンを無視することを選択した場合。ただし、ほとんどのコードはこれらのタイプを使用して記述されておらず、モデルが既存のバリエーションから逸脱した場合に混乱するコードには、通常、根深い、大部分が隠された(ただし根本的に欠陥のある)仮定があります。

64ビットWindows用のMicrosoftの非常に保守的なLLP64モデルに注目してください。これが選択されたのは、32ビットモデルが変更された場合に古いコードが多すぎると破損するためです。ただし、ILP64またはLP64アーキテクチャに移植されたコードは、違いがあるため、LLP64にすぐに移植できませんでした。陰謀論者はおそらく、64ビットUnix用に書かれたコードを64ビットWindowsに移植することをより困難にするために意図的に選択されたと言うでしょう。実際には、それが(Microsoftにとって)幸せな副作用以上のものであったかどうかは疑問です。LP64モデルも利用するには、32ビットのWindowsコードを大幅に修正する必要がありました。

于 2010-12-31T22:38:15.150 に答える
2

intが64ビットの場合に壊れてしまうコードイディオムが1つあり、それは合理的と言えるほど頻繁に見られます。

  • 次の場合をテストして、値が負であるかどうかを確認します。((val & 0x80000000) != 0)

これは通常、エラーコードのチェックで見られます。多くのエラーコード標準(WindowのようなHRESULT)は、エラーを表すためにビット31を使用します。また、コードは、ビット31をテストするか、エラーが負の数であるかどうかをチェックすることによって、そのエラーをチェックする場合があります。

HRESULTをテストするためのMicrosoftのマクロは両方の方法を使用します。そして、SDKマクロを使用せずに同様のことを行うコードがたくさんあると確信しています。MSがILP64に移行した場合、これは、LLP64モデル(またはLP64モデル)で完全に回避される移植の頭痛の種を引き起こした1つの領域になります。

注:「ILP64」などの用語に慣れていない場合は、回答の最後にあるミニ用語集を参照してください。

これらのintのサイズが32ビットであると仮定すると、エラーコードを保持するためにplain-old-intを使用するコード(必ずしもWindows指向である必要はありません)がたくさんあると確信しています。そして、両方の種類のチェック(< 0およびビット31が設定されている)も使用し、ILP64プラットフォームに移動すると壊れてしまう、そのエラーステータススキームを備えたコードがたくさんあるに違いありません。これらのチェックは、符号拡張が行われるようにエラーコードが注意深く構築されていれば、どちらの方法でも正しく機能し続けることができますが、繰り返しになりますが、私が見たそのようなシステムの多くは、ビットフィールドの束を組み合わせてエラー値を構築します。

とにかく、これは決して解決できない問題ではないと思いますが、ILP64プラットフォームに移行すると、多くのコードを修正する必要がある、かなり一般的なコーディング手法だと思います。

また、これがMicrosoftがLLP64モデルを選択した最大の理由の1つではないと思うことにも注意してください(MSDN以降で説明されているように、決定は主に32ビットプロセスと64ビットプロセス間のバイナリデータの互換性に基づいていると思います。 Raymond Chenのブログ)。


64ビットプラットフォームプログラミングモデル用語のミニ用語集:

  • ILP64:、、intポインタlongは64ビットです
  • LP64: longポインタは64ビット、int32ビットです(多くの(ほとんどの?)Unixプラットフォームで使用されています)
  • LLP64:long longおよびポインターは64ビットでintあり、long32ビットのままです(Win64で使用)

64ビットプログラミングモデルの詳細については、「64ビットプログラミングモデル:なぜLP64なのか」を参照してください。

于 2010-12-31T04:37:59.257 に答える
1

私は個人的にこのようなコードを書くことはしませんが、それは複数の場所にあることは間違いありません...そしてもちろん、のサイズを変更すると壊れますint

int i, x = getInput();
for (i = 0; i < 32; i++)
{
    if (x & (1 << i))
    {
        //Do something
    }
}
于 2010-12-30T02:01:47.863 に答える
0

まあ、この話がまったく新しいわけではありません。「ほとんどのコンピューター」とは、デスクトップコンピューターを意味すると思います。すでに16ビットから32ビットへの移行がありましたint。今回は同じ進行が起こらないと言っていることはありますか?

于 2010-12-30T01:32:49.217 に答える
-1

特にありません。一部の64ビットアーキテクチャ(x64ではない)では、intは64ビットです。

この規格は、実際に32ビット整数を取得することを保証するものではなく、(u)int32_tが32ビット整数を保持できることだけを保証します。

これで、intがptrdiff_tと同じサイズに依存している場合、壊れている可能性があります。

Cは、マシンがバイナリマシンであることを保証するものではないことを忘れないでください。

于 2010-12-30T01:43:25.217 に答える