16

最近、Lua の共同作成者である Luiz H. de Figueredo と Roberto Ierusalimschy のインタビューを読み、Lua の設計と実装について説明しました。控えめに言っても非常に興味をそそられました。しかし、議論の一部で私の心に何かが浮かびました。Roberto は、Lua を「独立したアプリケーション」 (つまり、OS から何も使用しない純粋な ANSI C です) と述べました。Lua のコアは完全に移植可能であり、その純粋さのために多くの移植が可能であると述べました。より簡単に、これまで考えもしなかったプラットフォーム (ロボットや組み込みデバイスなど) にも対応できます。

今、これは私を不思議に思います。一般に、C は非常に移植性の高い言語です。では、C のどの部分 (つまり、標準ライブラリーの部分) が最も移植性が低いのでしょうか? また、ほとんどのプラットフォームで動作することが期待できるものは何ですか? 限られたデータ型のセットのみを使用する必要がありますか (例:shortと 多分を避けるfloat)? とシステムFILEはどうですか?そして?Lua はこれらすべてを回避しているようです。それは物事を極端にしていますか?それとも移植性の問題の根源ですか? これ以外に、コードの移植性を非常に高めるためにできることは何ですか?stdiomallocfree

私がこのすべてを尋ねている理由は、私が現在純粋な C89 でアプリケーションを作成しているためであり、可能な限り移植可能であることが最適です。私はそれを実装する際に中間の道を喜んで取ります (移植性は十分ですが、すべてを最初から書かなければならないほどではありません)。

最後の注意として、この説明はすべて C89 のみに関連しています。

4

6 に答える 6

14

Lua の場合、C 言語自体について不満を言うことはあまりありませんが、C 標準ライブラリには、無害で簡単に使用できるように見える多くの関数が含まれていることがわかりました。有効性のための入力 (不便であれば問題ありません)。C標準では、不正な入力の処理は未定義の動作であり、これらの関数が必要なことを何でも実行でき、ホストプログラムをクラッシュさせることさえある. たとえば、strftime を考えてみましょう。一部の libc は無効なフォーマット指定子を単純に無視しますが、他の libc (Windows など) はクラッシュします! 現在、strftime は重要な機能ではありません。理にかなったことをする代わりに、なぜクラッシュするのでしょうか? そのため、Lua は strftime を呼び出す前に入力の独自の検証を行う必要があり、strftime を Lua プログラムにエクスポートするのは面倒です。したがって、私たちはコアの自立を目指して、Lua コアでこれらの問題を回避しようとしました。しかし、Lua 標準ライブラリーはそれを行うことができません。その目的は、C 標準ライブラリーで使用できるものを含め、機能を Lua プログラムにエクスポートすることだからです。

于 2011-02-15T11:23:01.480 に答える
9

「独立型」は、C のコンテキストで特定の意味を持ちます。大まかに言えば、独立型ホストは、ライブラリ関数malloc/ freeprintfなどを含む標準ライブラリを提供する必要はありません。特定の標準ヘッダーは引き続き必要ですが、型と定義のみを定義します。マクロ (例: stddef.h)。

于 2011-02-15T00:36:07.710 に答える
6

C89 では、ホスト型とフリースタンディングの 2 種類のコンパイラを使用できます。基本的な違いは、ホスト型コンパイラは C89 ライブラリのすべてを提供するのに対し、フリースタンディング コンパイラは 、、、および のみを提供する必要がある<float.h>ことです。これらのヘッダーに制限すると、コードは任意のC89 コンパイラに移植できます。<limits.h><stdarg.h><stddef.h>

于 2011-02-15T00:52:41.417 に答える
5

これは非常に幅広い質問です。明確な答えを出すつもりはありませんが、代わりにいくつかの問題を提起します。

C 標準では、特定のものを「実装定義」として指定していることに注意してください。適合するプログラムは、適合するプラットフォーム上で常にコンパイルおよび実行されますが、プラットフォームによって動作が異なる場合があります。具体的には、

  • ワードサイズsizeof(long)あるプラットフォームでは 4 バイト、別のプラットフォームでは 8 バイトの場合があります。short、などのサイズにはintそれぞれlong最小値がありますが (多くの場合、相互に相対的です)、それ以外の場合は保証されません。
  • エンディアン。あるプラットフォームで別のプラットフォームにint a = 0xff00; int b = ((char *)&a)[0];割り当てることができ0ます。b-1
  • 文字エンコーディング\0は常に null バイトですが、他の文字がどのように表示されるかは、OS やその他の要因によって異なります。
  • テキストモード I/Oputchar('\n')あるプラットフォームでは改行文字を生成し、次のプラットフォームでは改行文字を生成し、さらに別のプラットフォームではそれぞれの組み合わせを生成する場合があります。
  • char の署名度charaが負の値を取ることができる場合とできない場合があります。
  • バイトサイズ。今日では、事実上どこでも 1 バイトは 8 ビットですが、C は、そうでないいくつかの特殊なプラットフォームにも対応しています。

さまざまなワード サイズとエンディアンが一般的です。文字エンコーディングの問題は、あらゆるテキスト処理アプリケーションで発生する可能性があります。9 ビット バイトのマシンは、博物館で見つかる可能性が最も高いです。これは決して網羅的なリストではありません。

(そして、C89 を書かないでください。これは時代遅れの標準です。C99 は、固定幅の整数int32_tなど、移植性のためにいくつかの非常に便利なものを追加しました。)

于 2011-02-15T01:02:29.073 に答える
3

C は、コンパイラが任意のプラットフォーム用のコードを生成し、コンパイルする言語を「C」と呼ぶように記述できるように設計されました。このような自由は、C があらゆるプラットフォームで使用できるコードを作成するための言語であることに反するものです。

C のコードを書く人は誰でも (意図的に、またはデフォルトで)intサポートするサイズを決定する必要があります。の任意の正当なサイズで動作する C コードを作成することは可能ですがint、かなりの労力が必要であり、結果のコードは、特定の整数サイズ用に設計されたコードよりもはるかに読みにくくなることがよくあります。たとえば、xtype の変数がありuint32_t、それを別の で乗算してy結果 mod 4294967296 を計算したい場合、ステートメントは 32 ビット以下または65 ビット以上のx*=y;プラットフォームで動作しますが、場合にはintintUndefined Behaviorintは 33 ~ 64 ビットであり、オペランドが mod 4294967296 をラップする代数環のメンバーではなく整数と見なされた場合、積は を超えINT_MAXます。intのように書き直すことで、ステートメントを のサイズに関係なく機能させることができますx*=1u*y;が、そうするとコードがわかりにくくなり1u*、掛け算の 1 つから誤って を省略すると悲惨な結果になる可能性があります。

現在のルールの下では、整数サイズが期待どおりのマシンでのみコードが使用される場合、C は適度に移植可能です。のサイズが期待と一致しないマシンではint、言語の型付け規則のほとんどを無関係にするのに十分な型強制が含まれていない限り、コードは移植可能ではない可能性があります。

于 2015-06-19T16:57:08.080 に答える
2

C89 標準の一部であるすべてのものは、その標準に準拠する任意のコンパイラに移植できる必要があります。純粋な C89 に固執する場合は、かなり簡単に移植できるはずです。移植性の問題は、コンパイラのバグまたはコードが実装固有の動作を呼び出す場所が原因です。

于 2011-02-15T00:37:26.847 に答える