C言語の文字マクロ部分についての疑問

このQ&Aのポイント
  • C言語で使用される文字マクロ部分についての疑問について質問します。
  • 特に、__MINGW32__や__arch64__などの定義に関して疑問があります。
  • また、#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)の意味もわかりません。
回答を見る
  • ベストアンサー

Cで書かれたコードの文字マクロ部分がわかりません。

下記に示す、Cのサンプルプログラムの文字マクロの部分がわからず、困っています。 ソースの実行環境の違いを吸収するための部分であることはわかるのですが、どうしてこのようにて定義されたのかがわかりません。 特に、 ●__MINGW32__とは何か? ●#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)のところで、なぜ||と&&を併用しているのか。&& !defined(__MINGW32__)がどうして必要なのか? ●C##UI64、C##UL、C##ULLはそれぞれ何なのか? ●__arch64__は何か?なぜ必要なのか? ●なぜ、下のソース(文字マクロ部分)のdefineの流れになったのか? のあたりがわかりません。よろしくお願いします。 ---------------------------------------------------------------------- #if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) typedef unsigned __int64 u64; #define U64(C) C##UI64 #elif defined(__arch64__) typedef unsigned long u64; #define U64(C) C##UL #else typedef unsigned long long u64; #define U64(C) C##ULL #endif ----------------------------------------------------------------------

  • g47040
  • お礼率55% (125/226)

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

●__MINGW32__とは何か? ターゲットがMinGWの時に定義されるマクロ。 MinGWが何者かは↓あたりを参照 http://ja.wikipedia.org/wiki/MinGW ●#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)のところで、なぜ||と&&を併用しているのか。&& !defined(__MINGW32__)がどうして必要なのか? ||や&&は C自体でも使われている論理演算子です。この意味はよろしいですか? MinGWで使われる gcc と、標準的にWindowsで使われる Visual C++とでは、細かい点で使用がことなります。 ターゲットがWindowsであることを示す _WIN32や_WIN64だけでは、この二つの区別ができません。 この行は「32bit Windowsか64bit Windows用だけども、MinGW用ではない」という条件になります。 ●C##UI64、C##UL、C##ULLはそれぞれ何なのか? ## は演算子で、二つの文字列を継げます。 C##UI64 の場合。このCは関数マクロの引数なので u64(10) と記述すると、コンパイル前に 10UI64 に置き換わります。 詳細は「C言語 マクロ 演算子」で検索 UL 等は「サフィックス」と呼ばれるもので、その定数が何型かを明示するものです。 通常、整数定数はint型です。 例: 10 → int型の10 サフィックスUを付けると「unsigned」Lを付けると「long」になります 例: 10UL → unsigned longの10 ●__arch64__は何か?なぜ必要なのか? gccで64bitCPUがターゲットのとき定義されるようです。 ●なぜ、下のソース(文字マクロ部分)のdefineの流れになったのか? この例の場合。 どの型が何ビット使うかは、環境によって違います。 プログラム中で符号無し64bit整数を扱いたい場合、特定ターゲット用ならそのターゲットに合せて型を選べばよいですが、移植を考えるとよくありません。また、型が違えばサフィックスも変わります。 そこで、符号無し64bit整数の型u64 と、u64の定数を表記するためのマクロ U64 を用意して、コンパイラによって自動で適切な型に定義させ、プログラム本体では極力変更が無いようにする、というのがこのマクロの目的です。 ・Visual C++はgccとは型もサフィックスも違うので、専用の定義を使う ・Windows用でもMinGWはgccを使うので、Visual C++用設定は使わない。 ・それ以外では、64bitCPUではlongが/32CPUでは long long が64bitになっているので、それに設定する

g47040
質問者

お礼

お礼が遅れて申し訳ありません。 詳しいご回答ありがとうございました。 ありがとうございました!

関連するQ&A

  • C++ operator演算子の動作について

    下記プログラムを実行した時のoperator演算子の動作についての質問になります。 (VC++2010で動作確認) #include <iostream> struct UInterger { unsigned long ul_ui; UInterger( unsigned long ul_value ) : ul_ui( ul_value ) {} operator unsigned short() { return (unsigned short)ul_ui; } //(1)の時になぜ使用される?. operator unsigned int() { return (unsigned int)ul_ui; } operator unsigned long() { return (unsigned long)ul_ui; } }; int main() { UInterger s_uin(2); int i_temp = s_uin; // (1)コンパイルが通る. short s_temp = s_uin; // (2)コンパイルエラー. long l_temp = s_uin; // (3)コンパイルエラー. return 0; } (2)と(3)はoperatorの定義がないためコンパイルエラーとなるのは理解できます。 (1)でなぜコンパイルが通るのかがわかりません。 下記の定義を追加しない限り、コンパイルは通らないのではと考えております… operator int() { return (int)ul_ui; } 試しに(2)と(3)をコメントアウトしてステップ実行したところ (1)の時に下記のunsigned short()のオペレータが使用されておりました。 operator unsigned short() { return (unsigned short)ul_ui; } どなたか詳しい方、ご教授の程よろしくお願い致します。

  • あるマクロ処理の処理内容についての質問

    閲覧して頂いてありがとうございます。 C言語を勉強中なのですが、あるプログラムの中に どんな『処理』をしているかわからないマクロ関数があります。 下記Sampleコードの『#define test(n,a,k)』ですが、 一体どのような処理をしているか、ご教授頂けないでしょうか。 漠然とした質問で申し訳ありませんが、よろしくお願い致します。 [Sampleコード] #include <stdio.h> #define UL unsigned long #define UC unsigned char #define test(n,a,k) \ { \ (n) = ((UL)a[k]) \ | ((UL)a[k + 1] << 8) \ | ((UL)a[k + 2] << 16) \ | ((UL)a[k + 3] << 24); \ } int main(void){ UC hoge[] = {"1234567890_1234567890_1234567890_1234567890_1234567890"}; UL buf[4]; UL i; UC *p; p = hoge; test(buf[0], p, 0); test(buf[1], p, 4); test(buf[2], p, 8); test(buf[3], p, 12); for(i = 0; i < sizeof(buf)/sizeof(buf[0]); i++){ printf("%d\n",buf[i]); } return 0; }

  • typedef unsigned int UINT;があるか確かめる方法は?

    お世話になります C++で、 typedef unsigned int UINT; って、宣言があると思うのですが、 "typedef"宣言って、 #if defined(...) の、ように、宣言があるか確かめる方法ってあるのでしょうか? よろしくお願い致します

  • C言語に直して下さい

    VisualC++で円周率を求めるプログラムなのだそうですが、 自分はC言語しか使ったことがないため、よく分かりません。 Cでコンパイルできるように直していただけないでしょうか。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 21 #define K 100000 void add(unsigned long a[],unsigned long b[]) { int c = 0, tmp; for (int i = N - 1; i > -1; i--) { tmp = a[i] + b[i] + c; a[i] = tmp % K; c = tmp / K; } } void sub(unsigned long a[],unsigned long b[]) { int c = 0, x = 0; for (int i = N - 1; i > -1 ; i--) { x = c; if (a[i] < b[i] + x ) c = 1; else c = 0; a[i] = c * K + a[i] - b[i] - x; } } void div(unsigned long a[], unsigned long x) { int c=0, tmp; if (x >= K) { printf("Div Error\n"); getchar(); exit(1); return; } for (int i = 0; i < N ; i++) { tmp = (a[i] + c * K) / x; c = (a[i] + c * K) % x; a[i] = tmp; } } void clear(unsigned long a[]) { memset(a,0x00,sizeof(a)*N); } void set(unsigned long a[], unsigned long b[]) { memcpy(a,b,sizeof(a)*N); } void set(unsigned long a[], unsigned long b) { if (b<K) { clear(a); a[0]=b; } } int _tmain(int argc, _TCHAR* argv[]) { unsigned long pai[N], fn[N], gn[N], tmp1[N], tmp2[N]; int i; unsigned long n; clear(pai); clear(fn); clear(gn); clear(tmp1); clear(tmp2); set(fn, 16*5); set(gn, 4*239); for(n=0;n<40000;n++) { div(fn, 25); div(gn, 239); div(gn, 239); set(tmp1, fn); div(tmp1, 2*n+1); set(tmp2, gn); div(tmp2, 2*n+1); if (n%2==0) { add(pai, tmp1); sub(pai, tmp2); }else{ add(pai, tmp2); sub(pai, tmp1); } } for (i=0;i<N;i++) { printf("%5lu ", pai[i]); } getchar(); return 0; }

  • 相互に参照する構造体について

    Cプログラミングについての質問です。よろしくお願いします。 以下のヘッダファイル(defx.h, defy.h)および、mainファイルが正しくコンパイルされるということなのですが、自分の環境(WinXP下でのgcc(MinGW))ではエラーが出ます。 エラー内容は error: redefinition of typedef 'SY' error: previous declaration of 'SY' was here error: redefinition of typedef 'SY' error: previous declaration of 'SY' was here です。 <defx.h> #if !defined(__SX) #define __SX typedef struct __sy SY; typedef struct { int a; SY *b; } SX; #endif <defy.h> #if !defined(__SY) #define __SY #include "defx.h" typedef struct __sy { int c; SX d; } SY; #endif mainファイルについては #include "defx.h" #include "defy.h" int main(void) { SX s; SY t; } 以上ですが、 よろしくお願い致します。

  • PICC  ビルドトラブル

     宜しくお願いします。  あるソースファイル(net から入手)を ビルド しましたら 次のような メッセージ が 出ました。 これは どうしてでしょうか。 usart.h の 情報 も コピー します。  Error [141] C:\Users\tadao\Desktop\1207\0702_3.c; 3.18 can't open include file "usart.h": No such file or directory  #ifndef _SERIAL_H_ #define _SERIAL_H_ #define BAUD 9600 #define FOSC 4000000L #define NINE 0 /* Use 9bit communication? FALSE=8bit */ #define DIVIDER ((int)(FOSC/(16UL * BAUD) -1)) #define HIGH_SPEED 1 #if NINE == 1 #define NINE_BITS 0x40 #else #define NINE_BITS 0 #endif #if HIGH_SPEED == 1 #define SPEED 0x4 #else #define SPEED 0 #endif #if defined(_16F87) || defined(_16F88) #define RX_PIN TRISB2 #define TX_PIN TRISB5 #else #define RX_PIN TRISC7 #define TX_PIN TRISC6 #endif /* Serial initialization */ #define init_comms()\ RX_PIN = 1; \ TX_PIN = 1; \ SPBRG = DIVIDER; \ RCSTA = (NINE_BITS|0x90); \ TXSTA = (SPEED|NINE_BITS|0x20) void putch(unsigned char); unsigned char getch(void); unsigned char getche(void); #endif  C:\Users\tadao\Desktop\1207  以上 宜しくお願いいたします。 0256  

  • なぜマクロ「_WIN64」が未定義になるの?(Visual C++)

    下記環境で、32bitアプリケーションの64bit化をしようとしました。   OS    :Windows XP Professional x64 Edition   開発環境:Visual Studio 2008 Professional Edition   言語   :Visual C/C++ その際のビルドは、構成マネージャのアクティブソリューションプラットフォームを「x64」に設定してから行いました。 ところが、64bitアプリケーションなら定義されるはずの「_WIN64」というマクロが未定義になってしまいます。 なぜなのか、教えて欲しいです。 ちなみに、マクロが未定義かどうかは、   #if defined(_WIN64)     #define test   #endif の2行目がビルド後、灰色表示になるかどうかで確かめました。 その結果、灰色になりました。 さらに、補足ですが 64bitアプリケーションになっているかを確かめるため、 sizeof(int*)の値を確認したところ、 その値は「8」でした。 参考:   [MSDN Visual C++ デベロッパー センター]    http://msdn.microsoft.com/ja-jp/library/b0084kay.aspx    http://msdn.microsoft.com/ja-jp/library/9yb4317s(VS.80).aspx

  • callocの最大確保サイズについて…

    こんにちは 久しぶりにここに来ましたが… それで、callocを使ってメモリの動的確保をする部分をプログラムに入れましたが、 現在私が使用しているLSI C-86 試食版というコンパイラで、 ヘッダファイルを見ると、callocの何個確保確保するかに当たるsize_t型が typedef unsigned size_t; と定義されています。 sizeof(size_t)で確認してみると、2バイト(16ビット)ということがわかりましたが、すると、 callocで最大が65536個分しか確保できないということになるはずでして… とりあえずソースファイルの一番最初に以下の4行を追加してみましたが実行すると見事にエラーが出ました^^; #ifndef __SIZE_T_DEFINED #define __SIZE_T_DEFINED typedef unsigned long size_t; #endif コンパイラによってはsize_t型が違うかもしれませんが… できれば64kb以上のメモリ確保をしたいので、何かいいアイデア(ライブラリ関数等)があれば暇なときにでもご教授お願いします。 長々となりましたが、よろしくお願いします。

  • C++ basic_ostreamの拡張

    UTF-16文字列を扱うためのostreamを用意したいのですが、wcoutの代わりに、unsigned shortを用いたostreamを使いたいと思いました。 そこで、basic_ostreamのクラスのunsigned short型のインスタンスを作ったのですが、以下のエラーが出てしまってコンパイルが出来ませんでした。 「error C2296: '<<' : 無効です。左オペランドには型 'u16ostream (__cde cl *)(void)' が指定されています。」 「error C2297: '<<' : 無効です。右オペランドには型 'u16char *' が指定 されています。」 コンパイラはVC++2008です。 それとついでですが、通常通りwcoutを使う時みたいに、localeを設定する必要はあるのでしょうか? 回答、よろしくお願いします。 /* 以下ソースコード */ #include <iostream> typedef unsigned short u16char; typedef basic_ostream<u16char> u16ostream; int main() { u16ostream ucout(); u16char* str = (u16char*)(L"ああ"); ucout << str << '\n'; return 0; }

  • 大きな数の乱数を作るには

    C 初心者です。 表題のように、unsigned longのスケールの乱数をつくりたいんですが、以下のように記述すると値がいつも同じになります。この理由と、正しく動作するにはどう直したらいいのか教えてください。 unsigned long ul; ul = 4294967295UL * rand() / (RAND_MAX + 1); 値は常に131071でした。

専門家に質問してみよう