• ベストアンサー

CおよびC++におけるtypedefの厳密な扱われ方

お世話になっております。 主に3D系のゲームプログラマをしている者です。 今更こんな基本的な事を聞くのもお恥ずかしいのですが、出来るだけ正確な確認をしたいので、 皆様のお力を借りれたらと思います。 知りたい部分は、typedefで型再定義された物は、 元の型と全く同じ型として扱われると思って問題ないのか。 と言う事です。 typedefは、型の同義語を作る。 とあり、型名を簡略化する目的で使用されるのが一般的な使われ方ですが、型の同義語。 と言うのは、完全に、同じ型ではあるが名前だけが違う。と言う別名定義(defineの如く)として 見て良いのでしょうか? 例えば、 typedef int INT_A; void func (int param); /* 通常のintで仮引数を取る */ int main(void) {  INT_A num = 0; /* 再定義したINT_Aで変数を宣言し */  func(num); /* 通常intの仮引数にINT_Aで引数を渡す */  return 0; } 等とした場合、問題ないでしょうか。 特に問題ない事は幾つかの処理系で確認していますし、自身問題ないだろうと思っていますが、 厳密に言えば推測の域を出ないので困っています。 参考書やネット、経験からの勝手な推測では、defineならプリプロセッサにより、 コンパイル前にテキストレベルでの置き換えが行われるので同一。 typedefはコンパイル時解釈とあるので、同じ型と解釈して、 オブジェクトファイル等のバイナリレベルに落とす際に同一物にしてしまう。 等の変換を処理系で行っているのなら、同一なのかな。等と思っています。 (私は処理系の開発等はした事がありませんし、知識もソフ開レベル程度があるだけです) また、上記コードはC/C++どちらでも適用出来ますが、 C++はCと比べ、型の違いをより厳密に見ると聞きます。 ネットや参考書、経験則と言った類からの意見ですと質問した意味が ありませんので、 なるべくなら、X3010および、X3014(ANSIやISOも可)の規格から見て、上記の様な コードが全く問題ないのかどうか、ご教示頂けると幸いです。 (私は規格を持っていませんので・・・) また、上の例はサンプルであり、使い方等におけるコードの 可読性や意義に関しては、ここでは別問題とします。 以上、宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

>X3010および、X3014(ANSIやISOも可)の規格から見て、 日本工業標準調査会のホームページで 無料でWEB観覧できますので自分で見た方が良いかも。 ちなみにX3010では以下のように明記されています。 X3010 6.7.7 typdef宣言は新しい型を導入するのではなく、 指定した型の同義語だけを導入する。

参考URL:
http://www.jisc.go.jp/
PG_RankB
質問者

お礼

ありがとうございます。 だいぶ前にネットで規格を確認しようとした所、見れなかったので、 見れない物と思い込んでおりました。 (多分社内サーバの不調とかが原因だったのでしょうが) Cの規格、該当箇所を確かに確認致しました。 >typdef宣言は新しい型を導入するのではなく、 >指定した型の同義語だけを導入する。 と言う文面から、やはり問題ないと考えて差し支えないと判断します。 また、X3014でC++の方も探しましたが、7.1.3にtypedefの記述を 確認しました。一部省略しつつ抜粋すると、 ・typedef指定子をもつ<宣言>は、<識別子>を宣言し、後で基本型、  または複合型を名指すことができるようにする。 ・typedef指定子によって宣言された名前は、<型定義名>となり、  その宣言の有効範囲内では、構文規則上ではキーワードと同等と  し、その識別子に結びついた型を名指す。 ・型定義名は、クラス宣言又は列挙体宣言とは異なり、新たな型を  作り出しはしない。 等があり、自分の認識と同じである事を再確認致しました。 スッキリしました。有り難うございました。 (しかし、C90やC95の規格は相当前に無くなってしまいましたね。 どうせなら、C99以前の規格も拝見してみたいのですが・・・)

その他の回答 (1)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

> 元の型と全く同じ型として扱われると思って問題ないのか。 その認識で問題ありません。

PG_RankB
質問者

お礼

いつもお世話になっております。 返答ありがとうございました。

関連するQ&A

  • C++のtypedefについて

    C++のtypedefについて C++(Borland C++ Builder V5)で以下のようなソースがありました。 『typedef int (func)(Xclass* pXcls);』 これって関数ポインタの定義でしょうか? 関数ポインタの定義の場合は以下のようになるのではないのでしょうか? 『typedef int (*func)(Xclass* pXcls);』 ご教授お願いいたします。

  • 関数ポインタを返す関数の型をtypedefする方法

    C言語について質問します。 ある関数を定義するとします。 その関数は引数としてintを一つ取り、返値としてその関数と同じ型の関数へのポインタを返すようにしたいのですが、どのように書けばよいのでしょうか? そして、その関数の型をtypedefで定義したいです。 例えば、FNをtypedefしたいその関数の型だとすると、 typedef FN (*FN)(int); のようなFNを定義したいのですが、上のように書いても当然コンパイラ(VC9)に怒られます。 最悪、 typedef void* (*FN)(int); とvoidポインタを返すように定義しておいて、そのポインタを返値として受け取った側でFNにキャストし直す方法で対処できなくもないですが、ちょっと強引過ぎる気がします。 何かいい方法はあるのでしょうか? boost::functionあたりを使えばできそうな、そうでもないような気がしますが、できれば純粋なCでの解決法を望みます。 よろしくお願いします。

  • C言語のtypedefの質問

    Cビギナーです。 私のプログラムが長くなるのは、 ファイルの分割をしてないからだと知った今日この頃なのですが、 それを勉強するためにあるホームページを見ていたのですが、 次のようなサンプルプログラムがありました。 /* main.c */ #include <stdio.h> extern int func(int); typedef int (*pf)(int); extern pf getaddress(void); int main(void) { printf("%d\n",(getaddress())(4)); return 0; } /* sub.c */ static int func(int c) { return c*10; } typedef int (*pf)(int); pf getaddress(void) { return func; } ここで、typedef int (*pf)(int);の部分が分かりません。 intを(*pf)(int)で置き換えているのでしょうが、 それ自体がどういう意味か分かりません… どなたか教えて下さい。

  • C++/Cこういうことは可能でしょうか?違う型の引数をとって同じようなことをする

    お世話になります。 C++の初心者です。 違う引数をとって同じ関数にいれて同じようなことをさせるというのは できるのでしょうか? コンストラクタの作成方法で可能?? 共用体で可能?? 例: 型の違う構造体A,Bがある。 構造体のメンバには同じstatusが存在する。 statusが1のときだけresultを+し値を返す。 typedef struct{   int status;   int b; } DATA_A; typedef struct{   int status;   int b;   int c; } DATA_B; int test(DATA_AかDATA_Bを引数でとる,int data_num){ //data_numはデータ数  int i=0;  int counter=0;  for(i=0;i<data_num;i++){   //DATA_AまたはDATA_Bのメンバstatusが1ならcounterを+する   if(DATA_A.status == 1){    counter++;   }  }  return counter; } 以上のような感じです。 引数の型が違う2つの関数を作ればできますが、 同じことをさせるので同じ関数で実現できないかなと思って 質問させてもらいました。 よろしくおねがいします。

  • 関数ポインタの型をtypedefしたとき

    C言語において、関数ポインタの型をtypedefで作ると、 typedef int (*MyFunc)(int*,int*); と宣言でき、関数ポインタの変数は、 int FuncA(int* a, int* b) { ~ } void main_loop() { MyFunc pf = FuncA; ~ (*pf)(pa,pb); } というように使うと思います。 ここで疑問なのですが、この実際に呼び出される関数、FuncAの定義に、typedef(ここではMyFunc)を使えないものでしょうか? 同じことを2回やっているようで、無駄に思えてしまいます。

  • templete における typedef

    C++の初心者用的な本を買ってきて、 C++でテンプレートの部分を初めて勉強しています。 その中で、自分で理解できなかった部分が有り、 質問させていただきます。 本の中で「typedefで型指定しておく」という項目があり、 ~~~ もしクラステンプレートを多用する場合は、 typedefで型指定しておくのが 常套手段です。 ~~~ と2行くらいで書いてあり、 以下のサンプルが記述されていたのですが、 ~~~~~~ typedef mystack<int> int_stack; int_stack istk; ~~~~~~ 何のために、 templeteでtypedefを取り入れるのか? どうゆうときに、どんなありがたさがあるのか?が、 いまいち、理解でしませんでした。 どなたか、解説いただけるとありがたいです。 宜しくお願い致します。

  • C言語での関数形式マクロの使い方

    前の質問No.300834(関数形式マクロと空白の質問)と関連します。 関数形式マクロで、引数として入れるものは、変数でなくて型名でも構わないのでしょうか。 例えば、 #define mymul(t,x,y) ((t)(x)*(t)(y)) と定義すると、 mymul(int, 5.0, 3.5) と呼び出すと、 ((int)(5.0)*(int)(3.5)) に置き換える、 (intでキャストした 5.0 と、intでキャストした 3.5 をかける) というのは可能でしょうか。 あと、関数形式マクロの呼び出しは、実行部分でなくてもよいのでしょうか。関数頭部(関数の本体の前の部分)で呼び出せますか。 例えば #define ARGUMENT3(t1,v1,t2,v2,t3,v3) ¥ (t1 v1, t2 v2, t3 v3) #define a_func b_func ARGUMENT3 と定義しておいて、 関数を定義するときに、 int a_func(int,x, char*,cp, int**,ypp) { ・・・・ } こんなことをすると、 int b_func(int x, char *cp, int **ypp) { ・・・・ } に置き換わりますか? もし、ARGUMENT3の定義を、ARGUMENT3の後の括弧の中のカンマのつけ方を変えて、 #define ARGUMENT3(t1 v1,t2 v2,t3 v3) ¥ (t1 v1, t2 v2, t3 v3) とし、 int a_func(int x, char* cp, int** ypp) { ・・・・ } こうすると、先ほどのようなb_funcの関数頭部に変換することは出来ませんか? (関数形式マクロでこのような空白の入れ方をしてよいのでしょうか。)

  • マクロに同士計算できないの?

    #define NUM3 75+150 #define NUM7 75+350 定義がこのようにされています。 int c; c=NUM7 - NUM3; とすると、cに500が入るのですが、どうしてなんでしょうか・・。

  • 【C++】typedefの役割について

    C++だけでなく、Cでも同様なのだと思うのですが、下記の(1)、(2)の違い がよくわからず、どなたかにご教授いただければと思っています。 (1) struct{   (略) }BBB; (2) typedef struct{   (略) }BBB; (2)が下記((2)')のようになるんであれば、AAAという名前の構造体を BBBという名前で定義しているという事で理解できるんですが、 (2)のようにしている意図が理解できません。 (typedefの記述は必要なんでしょうか?) すでに動いているシステムなので、問題ないのは明らかなんですが。 (2)' typedef struct AAA{   (略) }BBB;

  • #defineでの型定義について

    typedefと同様に#defineでも型定義できると聞いて行いましたがコンパイルエラーが出てうまくいきませんでした。どうすればいいでしょうか? typedef unsigned int Unit //OK #deifine Unit unsigned int //NG

専門家に質問してみよう