ページ 1 / 1
関数形式マクロでエラー
Posted: 2013年5月04日(土) 15:51
by Sirius
関数形式マクロについてエラーが出てしまいました。
そのプログラムです
コード:
#include <stdio.h>
#define swap(type, a, b) ( type c, c = a, (a = b), (b = c) )
int main(void)
{
int x,y;
printf("マクロ\n");
printf("xの数を入力してください"); scanf("%d",&x);
printf("yの数を入力してください"); scanf("%d",&y);
swap(int, x, y);
printf("x=%d, y=%d\n", x, y);
return 0;
}
エラーメッセージは
コンパイル失敗
practice.c: 関数 ‘main’ 内:
practice.c:13:2: エラー: expected ‘)’ before ‘c’
practice.c:13:17: エラー: expected expression before ‘;’ token
と出ています
そこで3つ質問があります
1つ目です
なぜエラーになったのでしょうか(どこがいけなかったのでしょうか)
2つ目です
#define swap(type, a, b) ( type c, c = a, (a = b), (b = c) )
これを
#define swap(type, a, b) { type c; c = a; (a = b); (b = c); }
と書き換えるとコンパイル時にエラーが出ません
なぜなのでしょうか?
3つ目です
#define alert(str) (putchar('\a'), puts(str))
これはコンパイルができるのに
同じ()を使った
#define swap(type, a, b) ( type c, c = a, (a = b), (b = c) )
はなぜエラーになるのでしょうか?
C言語の知識は
配列や関数ぐらいまではでき、
ポインタや構造体はわかりません。
よろしくおねがいします。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 16:03
by softya(ソフト屋)
コンマ演算子の途中に変数定義が出来ないのでエラーになります。
それと()は式ですが、{}はステートメントです。同一には扱えません。
【補足】
こんな風には書けます。
#define swap(type, a, b) { type c; ( c = a, a = b, b = c ); }
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 16:41
by Sirius
わかりやすい回答有り難うございました。
コンマ演算子の途中で変数定義はできないのですね、初めて知りました。
()の式にしたかったのはif文のためです
例えば
#define swap(type, a, b) { type c; c = x; (x = y); (y = c); }
で
コード:
if(flag)
swap(int, x, y);
else
printf("フラグはたってません");
となった時に展開すると
コード:
if(flag)
{ type c; c = x; (x = y); (y = c); } //if文にかかった複合文
; //空文
else //どこにもかかっていないelse文
printf("フラグはたっていません");
となってしまいelseが実行されなくなることを恐れたからです
その場合
コード:
if(flag){
swap(int , x, y);
}else{
printf("フラグはたってません");
}
とやればいいのでしょうか?
できれば
コード:
if(flag)
swap(int, x, y);
else
printf("フラグはたってません");
とやり{ }は見栄え的に付けたくありません
しかしつけるしか方法はないのでしょうか?
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 16:50
by softya(ソフト屋)
{}で囲うぐらいしか手がないです。
それが嫌だとswapを関数にしてくださいって結論になりますね。
intが引数に出来なのでswap_int(&x, &y);とでもして頂いて。あっポインタを使うことになりますね。
C++なら、マクロを使わずにもっと綺麗に書けます。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 16:59
by Sirius
そうなのですか{ }やはりカッコを使うしかないのですね
やはり関数にすると汎用性が失われますし
{ }をつけるのは仕方が無いですね
C++ではもっと綺麗に書けるのですか・・・
とてもやってみたいのですが
しかしまだ僕はc言語の入り口のところをウロウロしているレベルですので
C言語がある程度できるようになってからC++には行こうと思います。
とてもわかりやすい回答の数々ありがとうございました
とてもすっきりしました
またこのサイトをつかわせてていただきたいとおもいます
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:04
by h2so5
こういうテクニックも存在します。
コード:
#define swap(type, a, b) do { type c; c = x; (x = y); (y = c); } while (0)
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:08
by ただの屍のようだ
マクロはあまり多用するものではないと思います。
たとえば:
コード:
int x=5,c=23;swap(int,x,c);
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:12
by softya(ソフト屋)
h2so5 さんが書きました:こういうテクニックも存在します。
コード:
#define swap(type, a, b) do { type c; c = x; (x = y); (y = c); } while (0)
それはオススメしないほうが良いような気がしたので避けました。
#define swap(type, a, b) for(;;) { type c; ( c = a, a = b, b = c ); break; }
#define swap(type, a, b) while(1) { type c; ( c = a, a = b, b = c ); break; }
とかヒドイのは思いつきますけどね。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:20
by softya(ソフト屋)
ただの屍のようださんの投稿は説明不足の様な・・・。
罠があると言いたんですよね。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:33
by Sirius
すみません
コード:
#include <stdio.h>
#define swap(type, a, b) do { type c; c = x; (x = y); (y = c); } while (0)
int main(void)
{
int x,y;
printf("マクロ\n");
printf("xの数を入力してください"); scanf("%d",&x);
printf("yの数を入力してください"); scanf("%d",&y);
swap(int, x, y);
printf("x=%d, y=%d\n", x, y);
return 0;
}
でコンパイルしたら
practice.c: 関数 ‘main’ 内:
practice.c:13:2: エラー: プログラム内に逸脱した ‘\343’ があります
practice.c:13:2: エラー: プログラム内に逸脱した ‘\200’ があります
practice.c:13:2: エラー: プログラム内に逸脱した ‘\200’ があります
コンパイル失敗
というエラーがでました。
どういうことでしょうか?
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:37
by みけCAT
プログラムに全角スペースが入っています。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:37
by softya(ソフト屋)
doの前に全角の空白が含まれてますね。半角にしてください。
h2so5さんのちょいミスでしょう。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:39
by Sirius
ただ屍のようだ様のこのプログラムは
私の理解力が低すぎてよくわかりませんでした
もう少し解説していただけないでしょうか?
コード:
int x=5,c=23;swap(int,x,c);
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:42
by ただの屍のようだ
自分のコードを展開するとint c; c = x; x = c; c = c; となるはずです。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 17:49
by Sirius
全角のスペースが含まれているのですねわかりました。
皆様ありがとうございました
話が変わってしまうのですがなぜ
コード:
#include <stdio.h>
#define swap(type, a, b) do { type c; c = x; (x = y); (y = c); } while (0)
int main(void)
{
int x,y;
printf("マクロ\n");
printf("xの数を入力してください"); scanf("%d",&x);
printf("yの数を入力してください"); scanf("%d",&y);
int flag =0;
if(flag)
swap(int, x, y);
else
printf("フラグはたってません");
return 0;
}
(意味がないプログラムですいません)
このプログラムでelseが実行されるのでしょうか?
(flagが0だからなのはわかっています
do~whileの効力について聞きたいです)
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 18:07
by softya(ソフト屋)
> do~whileの効力について聞きたいです)
ifからelse文は次の形式と決められています。
(1) if() {} else
(2) if() 単文; else
なのでどちらかに該当しないと行けません。
そこで(2)になるようにdoなど単文とみなされる書き方をトリッキーに使っているだけです。
ただ、やはり見た目にトリッキーなので推薦できないです。
Re: 関数形式マクロでエラー
Posted: 2013年5月04日(土) 18:12
by Sirius
そうなのですかdo~whileは短文扱いなのですね
わかりやすい解説有難うございました