はじめに
どうも、けーとらです。
最近、同期に質問されて、久々にダメ文字のエラーを見つけたので共有。
なんかエラーになるんだけど!?
と言いながら、同期に見せられたコードはこんな感じ。(流石に業務のコードは出せないからね)
#include <stdio.h> //テスト機能 int iFuncTest(); //メイン int main() { //テストの実行 printf("テストの実行\n"); iFuncTest(); return 0; } //テスト機能 int iFuncTest(){ //結果の出力 printf("テスト結果"); return 0; }
一見何の問題もなさそうで、VisualStudio上では構文エラーなども出ていない様子。
エラー内容
そしてエラーはこんな感じ。
./Main.c:10:5: warning: implicit declaration of function 'iFuncTest' is invalid in C99 [-Wimplicit-function-declaration] iFuncTest(); ^ ./Main.c:19:12: error: expected parameter declarator printf("テスト結果"); ^ ./Main.c:19:12: error: expected ')' ./Main.c:19:11: note: to match this '(' printf("テスト結果"); ^ ./Main.c:19:5: warning: type specifier missing, defaults to 'int' [-Wimplicit-int] printf("テスト結果"); ^ ./Main.c:19:5: error: conflicting types for 'printf' /usr/include/stdio.h:318:12: note: previous declaration is here extern int printf (const char *__restrict __format, ...); ^ ./Main.c:21:5: error: expected identifier or '(' return 0; ^ ./Main.c:22:1: error: extraneous closing brace ('}') } ^ 2 warnings and 5 errors generated.
コードには問題ないし…と5分くらい経ってから、あることに気が付いた。
VisualStudioでコーディング、別のコンパイラでコンパイルしているらしい。
なるほど、原因把握しました。
解決
最近は滅多に見なくなったのですが、所謂ダメ文字(後述)ですね。
てことで、16行目のコメントを「//」ではなく「/*」 と「*/」で囲う形にして解決。
#include <stdio.h> /*テスト機能*/ int iFuncTest(); //メイン int main() { //テストの実行 printf("テストの実行\n"); iFuncTest(); return 0; } /*テスト機能*/ int iFuncTest(){ //結果の出力 printf("テスト結果"); return 0; }
解決の報告だけしても仕方ないので、このようなバグが起こる原因を解説していきます。
C言語のコメント
最近では「//」も「/*」と「*/」で囲ってもコメントとして認識されます。
ただし、「//」はC++から輸入したもので、C99から利用できるようになりました。このため、組み込み系などでC99以前のC言語規格を利用する場合には「//」は使えないことを頭に入れておきましょう。
ダメ文字の原因となっているのはC言語の仕様で、「\」があると継続行とみなされて次の行を含めて1行だと認識することです。
この仕様が「//」コメントでも適用されてしまうため、次のように「//」コメントの最後に「\」があると次の行もコメントアウトされます。
#include <stdio.h> int main() { //次の行は実行されない\ printf("実行されない"); printf("実行される"); return 0; }
実行結果は次のようになり、6行目がコメントアウトされていることが分かります。
実行される
Shift JISのダメ文字
ここで問題になるのがShift JISの文字コードです。
Shift JISの2byte目には、C言語のメタ文字(特殊な意味を持つ文字)と同じバイト列が含まれることがあります。
例えば「表」や「能」は2byte目が「\」であり、これは先ほどのC言語の仕様にすると継続行としての意味を持ちます。このような文字のことをダメ文字と言い、Shift JIS特有の現象です。
これらを踏まえると次のコードが納得できるはずです。
#include <stdio.h> int main() { //次の行は実行されない機能 printf("実行されない"); //結果一覧表 //この行を消すと実行されない printf("実行される"); return 0; }
解決方法として
文字コードをUTF-8にするのが一番の解決策です。
どうしてもShift JISにこだわる必要があるのであれば、
- プログラム内に日本語を記述しない
- 「/*」と「*/」でコメントする
とかですかね。
最後に
なんでSJISのプログラムを使っていたのかは不明ですが、ダメ文字とかは当然把握しているべき事項でコーディング規約にも載ってなかったみたいです。
コードとは異なる部分が原因のエラーがたくさんあるから気をつけようねって感じですかね。
コメント