関数形式マクロでエラー

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Sirius

関数形式マクロでエラー

#1

投稿記事 by Sirius » 13年前

関数形式マクロについてエラーが出てしまいました。
そのプログラムです

コード:

#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言語の知識は
配列や関数ぐらいまではでき、
ポインタや構造体はわかりません。

よろしくおねがいします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 関数形式マクロでエラー

#2

投稿記事 by softya(ソフト屋) » 13年前

コンマ演算子の途中に変数定義が出来ないのでエラーになります。
それと()は式ですが、{}はステートメントです。同一には扱えません。

【補足】
こんな風には書けます。
#define swap(type, a, b) { type c; ( c = a, a = b, b = c ); }
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Sirius

Re: 関数形式マクロでエラー

#3

投稿記事 by Sirius » 13年前

わかりやすい回答有り難うございました。
コンマ演算子の途中で変数定義はできないのですね、初めて知りました。
()の式にしたかったのは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("フラグはたってません");
とやり{ }は見栄え的に付けたくありません
しかしつけるしか方法はないのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 関数形式マクロでエラー

#4

投稿記事 by softya(ソフト屋) » 13年前

{}で囲うぐらいしか手がないです。
それが嫌だとswapを関数にしてくださいって結論になりますね。
intが引数に出来なのでswap_int(&x, &y);とでもして頂いて。あっポインタを使うことになりますね。

C++なら、マクロを使わずにもっと綺麗に書けます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Sirius

Re: 関数形式マクロでエラー

#5

投稿記事 by Sirius » 13年前

そうなのですか{ }やはりカッコを使うしかないのですね
やはり関数にすると汎用性が失われますし
{ }をつけるのは仕方が無いですね

C++ではもっと綺麗に書けるのですか・・・
とてもやってみたいのですが
しかしまだ僕はc言語の入り口のところをウロウロしているレベルですので
C言語がある程度できるようになってからC++には行こうと思います。

とてもわかりやすい回答の数々ありがとうございました
とてもすっきりしました
またこのサイトをつかわせてていただきたいとおもいます

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 関数形式マクロでエラー

#6

投稿記事 by h2so5 » 13年前

こういうテクニックも存在します。

コード:

#define swap(type, a, b) do { type c; c = x; (x = y); (y = c); } while (0)

ただの屍のようだ

Re: 関数形式マクロでエラー

#7

投稿記事 by ただの屍のようだ » 13年前

マクロはあまり多用するものではないと思います。
たとえば:

コード:

int x=5,c=23;swap(int,x,c); 

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 関数形式マクロでエラー

#8

投稿記事 by softya(ソフト屋) » 13年前

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; }
とかヒドイのは思いつきますけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 関数形式マクロでエラー

#9

投稿記事 by softya(ソフト屋) » 13年前

ただの屍のようださんの投稿は説明不足の様な・・・。
罠があると言いたんですよね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Sirius

Re: 関数形式マクロでエラー

#10

投稿記事 by Sirius » 13年前

すみません

コード:

#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’ があります
コンパイル失敗
というエラーがでました。
どういうことでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 関数形式マクロでエラー

#11

投稿記事 by みけCAT » 13年前

プログラムに全角スペースが入っています。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 関数形式マクロでエラー

#12

投稿記事 by softya(ソフト屋) » 13年前

doの前に全角の空白が含まれてますね。半角にしてください。
h2so5さんのちょいミスでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Sirius

Re: 関数形式マクロでエラー

#13

投稿記事 by Sirius » 13年前

ただ屍のようだ様のこのプログラムは
私の理解力が低すぎてよくわかりませんでした
もう少し解説していただけないでしょうか?

コード:

int x=5,c=23;swap(int,x,c);

ただの屍のようだ

Re: 関数形式マクロでエラー

#14

投稿記事 by ただの屍のようだ » 13年前

自分のコードを展開するとint c; c = x; x = c; c = c; となるはずです。

Sirius

Re: 関数形式マクロでエラー

#15

投稿記事 by Sirius » 13年前

全角のスペースが含まれているのですねわかりました。
皆様ありがとうございました

話が変わってしまうのですがなぜ

コード:

#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の効力について聞きたいです)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 関数形式マクロでエラー

#16

投稿記事 by softya(ソフト屋) » 13年前

> do~whileの効力について聞きたいです)

ifからelse文は次の形式と決められています。
(1) if() {} else
(2) if() 単文; else
なのでどちらかに該当しないと行けません。
そこで(2)になるようにdoなど単文とみなされる書き方をトリッキーに使っているだけです。
ただ、やはり見た目にトリッキーなので推薦できないです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Sirius

Re: 関数形式マクロでエラー

#17

投稿記事 by Sirius » 13年前

そうなのですかdo~whileは短文扱いなのですね
わかりやすい解説有難うございました

閉鎖

“C言語何でも質問掲示板” へ戻る