ページ 11

関数形式マクロでエラー

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は短文扱いなのですね
わかりやすい解説有難うございました