#define WRITE_test(TEST) \
do{ \
fprintf(stderr, "%s can't open\n", #TEST); \
}while(0);
というマクロを書いた上で、ソースをコンパイルすると
/**/
if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
do{
fprintf(stderr, "%s can't open\n", "test");
}while(0);
else if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
do{
fprintf(stderr, "%s can't open\n", "test");
}while(0);
else
break;
とある箇所にエラーなどは現れず
/**/
if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
WRITE_test(test);
else if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
WRITE_test(test);
else
break;
とある箇所で、
「buf_.c:263: error: 構文解析エラー が "else" の前にあります」
というメッセージが現れます。263行とはひとつめのWRITE_test()がある箇所です。
マクロはテキストが置換、展開されるものと考えると、この結果に納得できないでおります。説明がつくでしょうか?
コンパイルはgentoo Linux上で/usr/bin/gcc-3.4.4によるものです。
No.2ベストアンサー
- 回答日時:
★原因はセミコロンをマクロ関数につけているからだよ。
if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
WRITE_test(test);
else if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
WRITE_test(test);
else
break;
↑上記を展開します↓
if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
do {
fprintf(stderr, "%s can't open\n", #TEST);
} while(0);;
else if (length_max/*LENGTH_buf_mpi*/ > length+strlen(buf_))
do {
fprintf(stderr, "%s can't open\n", #TEST);
} while(0);;
else
break;
となりますよね。
すると『while(0);;』でセミコロンが2つになります。
それで if 文に{ }のブロックがありませんので、次のように解釈されます。
if ( … ) do { … } while(0);
;
else if ( … ) do { … } while(0);
;
else break
普通に考えて
if ( … ) 次の1文
;
else break
↑
『else』の前にセミコロンつけるとエラーになりますよ。
よって、
#define WRITE_test(TEST) \
do{ \
fprintf(stderr, "%s can't open\n", #TEST); \
}while(0) ←セミコロンを取ればよい。
その他
・このような場合の為に if、else の{ }のブロックは省略しない方がよいのです。
もしも、if、else に{ }のブロックをつけて記述すれば、マクロにセミコロンが
あっても正しく処理されます。
・以上。マクロ関数にセミコロンをつける場合は注意して下さい。
一行目でヴィヴィッドに説明が伝わりました。ありがとうございます。たまたまこれまでelse以下をつけてこなかったので気づきませんでした。
if, elseの{}を省略しないことにするのはよさそうですけれど、この場合マクロのラスト、while(0)の後ろにセミコロンをつけない形にしておいて、ソースの中でマクロを使用する際には一般の関数に似せてセミコロンをつけることにするのがいいかなと考えました。
ご丁寧な説明、ありがとうございました。
No.5
- 回答日時:
★もしかして、複数の処理を1文で記述できるように do-while を使っているとか。
・昔、持っていた本に載っていたような気がした。
それで『do { 複数の処理 } while(0)』とマクロで定義しているのね。
私はif、else に{ }文字を省略しないのでマクロ関数に{ }文字のブロックで
囲んで定義することがあります。
#define MacroName( a, b )\
{\
宣言など\
\
/* コメント */\
処理1\
処理2\
:
処理n\
}\ ←私は、ここにも¥文字を付ける
←上に¥を付けているので必ず1行以上空行を空けて定義する。
その他:
・ここでは連続するタブ文字とスペースが1個になるので全角の空白を使って
インデントなどを表現できます。
・以上。参考に!
いくつか流儀があるのですね。
自分が参考になったところで大きく共通しているのは、{ }(do()while(0)を含めて)をつかうことでマクロの中で関数ライクに複数の処理を行える点、{ }内で各種の宣言が可能である点です。そこそこ本を読みながらプログラムを書いているつもりなのですけれど、このあたりのことは記憶に残る箇所に明らかにはされていませんでした。
このあたりをもっと早く知っていたら、デバッグの作業も数値計算上の確認もたいへん楽になっていたのに。ここのところで一番ためになった箇所です。
全角の空白をつかうことには違和感を感じるのですけれど、この場でこだわることはないですね。こちらもたいへん参考になりました。ありがとうございました。
No.4
- 回答日時:
その (do ... while (0) という) 形のマクロを自分で思い付いたんだったらすごいけど....
その形のマクロでは最後にセミコロンを付けないのが普通.
まあ, 1行なのに do ... while(0) ってのも冗長だけど.
見かけたことがあって、真似てみました。セミコロンをたぶんそこではつけていなかったのだと思います。細かいところまで把握し切れていなかったのですね。
こういうコツは、みなさんどこで習得するのでしょう?はじめて目にしたときはびっくりしました。おもに買いだめしたC言語の本とweb上の情報をもとに試行錯誤しているのですけれど、手元の資料にはこういう工夫は載っていません。
回答を締め切ったつもりでできていなかったのですけれど、この件を書き込んでしまうのでもう少し締め切るのを延長させてください。
1行であるのは、書いたマクロを本来の形からどんどん削っていって、それでもエラーが残って悩んでしまった結果です。
# トピックを外れていろいろ書くのはよろしくないとは思いますけれど、新しく書き込むほどのことはなさそうなのでもうひとつ。
投稿した後の画面では半角の空白やタブが消えてしまっていました。これにはどう対処すればよろしいのでしょうか?
No.1
- 回答日時:
gccの実装/仕様を確認したわけではないので憶測ですが…、
そのエラーメッセージは__LINE__に基づいてたり、
複数行に同じ__LINE__が割り当てられてたりはしないのでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Perl perl このテキストファイルを簡単に配列に入れるには? 2 2022/04/27 20:24
- Visual Basic(VBA) オブジェクトが見つかりません 1 2023/06/24 19:43
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Visual Basic(VBA) このマクロの説明文を教えてほしいです。 1 2023/01/12 09:17
- JavaScript vertical sliderをautoplayしたい 2 2022/08/25 14:47
- Excel(エクセル) 2つのVBAを一緒にしたら機能しなくなりました(エクセル) 7 2022/06/02 12:41
- Visual Basic(VBA) フォルダの場所を可変にしたいです(マクロ) 4 2023/05/11 10:00
- FX・外国為替取引 pine scriptのコードが動作しない 1 2023/02/01 19:03
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- Visual Basic(VBA) Excel-VBAでのファイルの開き方 4 2023/02/14 11:01
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Excel・Word リサーチ機能を無...
-
特定のPCだけ動作しないVBAマク...
-
エクセルで特定の列が0表示の場...
-
メッセージボックスのOKボタ...
-
一つのTeratermのマクロで複数...
-
Excel マクロ VBA プロシー...
-
ExcelのVBA。public変数の値が...
-
TERA TERMを隠す方法
-
エクセルで別のセルにあるふり...
-
Excel VBAからAccessマクロを実...
-
EXCELのVBAでRange("A1:C4")を...
-
組んだマクロをメールで送る
-
VBAにて別ワークブック上の実行...
-
ExcelVBAでPDFを閉じるソース
-
【Excel】複数のマクロをまとめ...
-
TeraTermマクロの文字列結合
-
Sub ***( ) と Private Sub ***...
-
バッチファイルでEXCELを起動し...
-
Excelで特定の文字のところで自...
-
Teraterm 1行空白を入れたい。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Excel・Word リサーチ機能を無...
-
特定のPCだけ動作しないVBAマク...
-
エクセルで特定の列が0表示の場...
-
Excel マクロ VBA プロシー...
-
メッセージボックスのOKボタ...
-
一つのTeratermのマクロで複数...
-
エクセルで別のセルにあるふり...
-
ExcelのVBA。public変数の値が...
-
エクセルに張り付けた写真のフ...
-
ExcelVBAでPDFを閉じるソース
-
EXCELのVBAでRange("A1:C4")を...
-
Excel VBAからAccessマクロを実...
-
TERA TERMを隠す方法
-
エクセルのマクロについて教え...
-
エクセルのマクロについて教え...
-
エクセルのマクロについて教え...
-
エクセルのマクロについて教え...
-
マクロ実行時、ユーザーフォー...
-
Excelのマクロについて教えてく...
-
ソース内の行末に\\
おすすめ情報