Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

typedefについて確認させてください

50 views
Skip to first unread message

IIJIMA Hiromitsu

unread,
May 28, 2003, 8:20:27 PM5/28/03
to
いいじまです。

「typedefで定義される型は、#if で演算に用いることはできない」
上記の命題はあっているでしょうか。

たとえば、こんなコードです。
//---システムが用意するヘッダファイル
typedef unsigned short wchar_t;

//---それを #include するコード
#if sizeof(wchar_t)==2
#define UCS2 wchar_t;
typedef uint_least32_t UCS4;
//後略

これはプリプロセッサの段階でエラーになるのが正しいんですよね。

#そもそも char が 8 ビットということすら規格は保証していないので、
#sizeof(short)==2 なんて無意味なんですが。

で、wchar_t に関しては素直に WCHAR_MAX を見て判定するのが吉、と。

========================================================================
飯嶋 浩光 / でるもんた・いいじま http://www.ht.sakura.ne.jp/~delmonta/
IIJIMA Hiromitsu, aka Delmonta mailto:delm...@ht.sakura.ne.jp

KATAYAMA Yoshio

unread,
May 29, 2003, 6:50:22 AM5/29/03
to
片山@PFUです。

In article <3ED5524B...@ht.sakura.ne.jp>,
IIJIMA Hiromitsu <delm...@ht.sakura.ne.jp> writes:

>「typedefで定義される型は、#if で演算に用いることはできない」
>上記の命題はあっているでしょうか。

typedef は typedef名を定義するものであって、型を定義するのでは
ありませんから、「typedef で定義される型」なるものは存在しません。

「typedefで定義される型」が「typedef で typedef名として定義され
る識別子」のことと解釈すると、これは、この段階では単なる識別子と
して扱われますので、#if の式に用いることができます。

#しかし、その値は 0 となるでしょう

>たとえば、こんなコードです。
> //---システムが用意するヘッダファイル
> typedef unsigned short wchar_t;

> //---それを #include するコード
> #if sizeof(wchar_t)==2

この #if の式は、

0 ( 0 ) == 2

と解釈され、構文エラーになります。

>これはプリプロセッサの段階でエラーになるのが正しいんですよね。

理由はともかく、結論だけは合っています。:-)
--
片山@PFU

IIJIMA Hiromitsu

unread,
May 29, 2003, 11:48:15 AM5/29/03
to
いいじまです。

> typedef は typedef名を定義するものであって、型を定義するのでは
> ありませんから、

なるほど、「typedef 名」という、きちんとした言葉があるんですね。

> >たとえば、こんなコードです。
> > //---システムが用意するヘッダファイル
> > typedef unsigned short wchar_t;
>
> > //---それを #include するコード
> > #if sizeof(wchar_t)==2
>
> この #if の式は、
>
> 0 ( 0 ) == 2
>
> と解釈され、構文エラーになります。

うわあ…
「識別子 wchar_t は未定義」という致命的エラーになると思っていたのですが、
そうではないのが規格として正しいのですね。

#そもそも #if の中では sizeof も使えないのか…

実際の処理系では
・#if の中で sizeof が使えるように独自拡張を施している
・未定義の識別子を使ったらエラーないし警告を出す
ものがあると思うので、余裕のあるときに複数の処理系で確認してみます。

> >これはプリプロセッサの段階でエラーになるのが正しいんですよね。
>
> 理由はともかく、結論だけは合っています。:-)

ありがとうございます。やはりこの場合は WCHAR_MAX を使うことになりますね。

歴史的にはCのコードのコンパイルはプリプロセッサ、パーサ、コードジェネ
レータ、アセンブラ、リンカの5段階で、typedef はパーサの担当だから、その
前のプリプロセッサが担当する #if では扱えないはず、規格もそれを追認する
規定をしているはず、と予想していました。

Shinji KONO

unread,
May 29, 2003, 10:06:57 PM5/29/03
to
河野真治 @ 琉球大学情報工学です。

In article <3ED62BBF...@ht.sakura.ne.jp>, IIJIMA Hiromitsu <delm...@ht.sakura.ne.jp> writes


> #そもそも #if の中では sizeof も使えないのか…

でも、#if じゃなくて、if で書けば良いと思いますけど。
なんか問題あるんですか?

> 実際の処理系では
> ・#if の中で sizeof が使えるように独自拡張を施している
> ・未定義の識別子を使ったらエラーないし警告を出す

自分で書いたものでは、macro の展開を1 pass で行うので、
sizeof は使えます。#if では未定義の識別子は0と判断する
のが便利だろうと想像します。自分のではエラーにしているな。

> ものがあると思うので、余裕のあるときに複数の処理系で確認してみます。

ってわけで、そんなものは(僕のもの以外)ないと思う。

---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)

IIJIMA Hiromitsu

unread,
May 30, 2003, 12:47:44 AM5/30/03
to
いいじまです。

> でも、#if じゃなくて、if で書けば良いと思いますけど。
> なんか問題あるんですか?

あ、普通はそっか。きちんと最適化オプションつければ if(0) はコンパイラが
丸ごと削除してくれますものね。

ただ今回の場合、自作のヘッダファイルで

#if WCHAR_MAX==0x7FFFUL || WCHAR_MAX==0xFFFFUL


#define UCS2 wchar_t;
typedef uint_least32_t UCS4;
//後略

と書いて、たとえば
UCS2 *foo(UCS2[]);
と関数を宣言して、Win32 環境ではこの foo() の引数に wchar_t の配
列を渡す、ということをしたいんですよ。OS の MultiByteToWideChar
は wchar_t の配列にデータを返すので。

で、wchar_t が UCS-2 の処理系では foo() に wchar_t の配列を渡して
も文句を言われず、かつ、wchar_t が UCS-4 の処理系、具体的に言うと
glibc とかでは foo() に wchar_t の配列を渡そうとするとエラーない
し警告になる、という仕様にしたいんです。

とすると、識別子 UCS2 は typedef ではなく #define で定義する必要
がある、というわけです。

…汚い方法です、はい。

IIJIMA Hiromitsu

unread,
May 30, 2003, 1:07:48 AM5/30/03
to
> #define UCS2 wchar_t;

はうっ。ここのセミコロンは余計。

Shinji KONO

unread,
May 30, 2003, 1:04:20 AM5/30/03
to
河野真治 @ 琉球大学情報工学です。

In article <3ED6E270...@ht.sakura.ne.jp>, IIJIMA Hiromitsu <delm...@ht.sakura.ne.jp> writes


> ただ今回の場合、自作のヘッダファイルで
> #if WCHAR_MAX==0x7FFFUL || WCHAR_MAX==0xFFFFUL
> #define UCS2 wchar_t;
> typedef uint_least32_t UCS4;

ってことなら、そのヘッダファイルを生成するようなconfigure script
書く方が最近は普通かも知れないですね。で、config.h をinclude
すると。

KATAYAMA Yoshio

unread,
Jun 2, 2003, 9:49:49 AM6/2/03
to
片山@PFUです。

In article <3ED62BBF...@ht.sakura.ne.jp>,
IIJIMA Hiromitsu <delm...@ht.sakura.ne.jp> writes:

>> typedef は typedef名を定義するものであって、型を定義するのでは
>> ありませんから、

>なるほど、「typedef 名」という、きちんとした言葉があるんですね。

ISO では「typedef name」ですが、JIS では何と訳しているかは分かり
ません。「typedef名」は、私が勝手につけた訳語です。(_ _;

>> > #if sizeof(wchar_t)==2


>>
>> 0 ( 0 ) == 2
>>
>> と解釈され、構文エラーになります。

>「識別子 wchar_t は未定義」という致命的エラーになると思っていたのですが、
>そうではないのが規格として正しいのですね。

>#そもそも #if の中では sizeof も使えないのか…

はい。

>実際の処理系では
>・#if の中で sizeof が使えるように独自拡張を施している
>・未定義の識別子を使ったらエラーないし警告を出す
>ものがあると思うので、余裕のあるときに複数の処理系で確認してみます。

規格に従うと、

1. 物理的なソースファイルのマルチバイト文字を文字集合に変換。
end-of-line indicator を改行文字に変換。
trigraph sequence を対応する単一文字内部表現へ変換。

2. 「\ + 改行文字」を削除して論理的なソースファイルへ変換。

3. 前処理トークンと空白類に分解。

4. 前処理命令の実行、マクロ呼出しの展開、_Pragma の実行。
#include 前処理命令では、取り込まれたヘッダー/ソースファイル
について、1~4 を再帰的に適用。

5. 文字定数/ストリングリテラルのソース文字集合要素とエスケープ
シーケンスを対応する実行文字集合要素へ変換。

6. 隣接するリテラルトークンの連結。

7. 前処理トークンをトークンに変換し、一つの transration unit と
して、構文/意味解析を行ない、翻訳する。

8. 外部オブジェクト/関数の参照を解決し、ライブラリコンポーネン
トをリンクし、一つのプログラムイメージにまとめる。

の 8 フェーズに分かれなければなりません。

「#if の中で sizeof が使えるように独自拡張」すると、規格合致では
なくなります。

「未定義の識別子を使ったら警告を出す」のは規格合致ですが、エラー
にすると規格合致ではなくなります。

>歴史的にはCのコードのコンパイルはプリプロセッサ、パーサ、コードジェネ
>レータ、アセンブラ、リンカの5段階で、typedef はパーサの担当だから、その
>前のプリプロセッサが担当する #if では扱えないはず、規格もそれを追認する
>規定をしているはず、と予想していました。

これを勿体ぶって^H^H^H^H^H厳格に定義したのだと思います。
--
片山@PFU

0 new messages