2011-01-12 16 views
5

しかし、私は自己促進のデータ型の意味を把握することができませんでした。彼らは何ですか&非自己昇進データ型とはどのように違いますか?自己推進のデータ型

答えて

4

ここにはC99 standardがあります。 「自己宣伝」型は、デフォルトの引数プロモーション(6.1.1.1項で説明した整数プロモーションを参照する§6.5.2.2パラグラフ6)が適用されるときに自らを促進するタイプです。

va_arg定義(§7.15.1.1)を読むと、この制限がであるということです。 [...]

または(デフォルト引数キャンペーンに による推進されるように)タイプは、実際の次の引数の型と互換性がない場合に...:関連部分は第2項です]昇格される実際の次の引数の型について非常に明確であるが、私はおよそタイプが推進されて何も言わないよう読ん

を。 (私は "(昇格された...)"節は、varargs関数が呼び出されたときに、引き続く引き数にデフォルトの引数昇格が実行されることを思い出させるものです)。

この項目は§ J.2この読み取りをサポートしてい

- 実際の次の引数、または実際次 引数の促進タイプと互換性がない 指定されたタイプとが存在しない場合va_argマクロが起動され、一定と例外(7.15.1.1)。

(私は知っていますが、附属書Jは「規範的」ではなく「有益」です...)。場合

va_arg(ap, float)(たとえば)有効にすることはできません - その場合にタイプfloatであるが、実際の次の引数の促進タイプは、おそらく(float引数はdoubleに昇格される)floatことができません。

+0

この制限は特にありませんか?おそらく 'va_arg'の実装と関係がありますか? –

+1

@crypto:私はZackが正しいと思う(Jensに対する彼の反応を参照)。コンパイラからの特別な助けなしに与えられた型のデフォルト引数昇格を見つける明白な方法がないので、このような助けなしに動作する 'va_arg(ap、type) 'の実装が可能になります。 (例えば、 'ap'のスタック上の現在の引数にバイトポインタを置いておくと、' va_arg'はそれを 'type *'にキャストして次の引数に移動し、 'type *'ポインタをインクリメントして、バイトポインタにキャストし直します)。 –

2

これはglibcの制限のようですが、C標準にはありません。

この背後にある考え方は、「変換ランク」、いわゆるいるという整数型であるintよりも小さいが、自動的にsignedまたはunsignedintに昇格されています。 va_arg関数はそのようなより広い引数を見つけます。 va_argマクロは、まず、タイプintのより広い引数を読んでから、元の型にキャストし直さなければなりません。

(同じことがdoublefloat w.r.tについても同様である。)

気づいていないプログラマのために、これは驚くべき結果を持つことができるので、私は、これは避けるべきであるという考えに同意します。引用している説明は、小さなタイプを使用しないように強制されていることを暗示しているようです。これは偽物であり、私は標準と一致していないと言っています。一方、コードを書いた場合、これは制限で拡張ではないので、移植性の問題は決してありません。

+2

私の知る限り、マシューは正しかったです。あなたは間違っています。この制限は少なくともC99では*です。それについて考えるなら、非常に難しいでしょう - 私は偽りはしませんが、Cの標準では、一般的には実装に難しい要求を単に置くことを避けています - "va_arg"の "従来の"実装を行う引数の宣伝が呼び出し元で行われる場合、この制限なしで、コンパイラ固有のものに展開されないもの)。 – zwol

+0

@Zack:言葉遣いが少なくともあいまいであると言うと、「昇格した...」の範囲は明確ではありません。しかし、私は狭いタイプを許すことは実装に多大な負担をかけるとあなたに同意しません。彼らは狭い型をチェックし、型の宣言を読んで(実装はその型を見つける方法を知っていなければなりません)、値を狭い型にキャストする必要があります。 –

+2

これはコンパイラの組み込み関数*から簡単に行うことができます。伝統的な 'va_arg'の実装は、そのような便利さにアクセスすることはできません。それは(技術的に定義されていない)コア言語表現ですべてを行います。 Cは型のメタプログラミングを行う方法を一切含んでいないので、あなたは "宣言された型の引数を見つけて、狭い型にキャストする"ことはできないと思います。 – zwol

関連する問題