致命的エラー

C言語のエラー C1017について解説:プリプロセッサでの整数定数式エラーの対処法

この記事では、C言語で発生するエラー C1017について解説します。

プリプロセッサディレクティブの#ifで、整数定数として評価されない値を指定するとエラーが発生します。

例えば、文字列として定義した定数を#ifで使用すると問題になるため、整数に修正する必要があります。

実際の例を通して対処方法を紹介します。

エラー C1017 の原因

C1017エラーの基本説明

エラー C1017 は、プリプロセッサが #if#elif などのディレクティブで使用される式が整数定数として評価できなかった場合に発生します。

具体的には、定義されたマクロが文字列定数など整数定数として認識されない値である場合、コンパイラは整数定数式が無効であるとしてエラーを報告します。

このエラーは、例えば #define CONSTANT_NAME "YES" のように定数を文字列として定義し、その後に #if CONSTANT_NAME のように利用する際に発生します。

プリプロセッサにおける定数評価の仕組み

C言語のプリプロセッサは、コンパイルの前処理段階でソースコード中のディレクティブを評価します。

具体的には、#if#elif で指定された式は、整数定数式として解釈される必要があります。

定数が整数として評価されなければ、エラー C1017 が発生します。

また、プリプロセッサは未定義の定数を自動的に 0 と評価するため、意図しない動作につながる可能性もあります。

数値定数と文字列定数の違い

プログラム中では、数値定数と文字列定数の扱いは大きく異なります。

・数値定数は、数式内で直接計算できるため、#if#elif で問題なく利用できます。

・一方、文字列定数は直接計算できず、整数として評価されないため #if などの条件式で使用するとエラーが発生します。

例えば、#define CONSTANT_NAME "YES" と定義すると、CONSTANT_NAME は文字列リテラルとして扱われ、整数定数としての評価ができません。

エラー発生例の詳細

発生するコード例の紹介

下記のコードは、エラー C1017 が発生する例です。

#include <stdio.h>
#define CONSTANT_NAME "YES"
int main(void) {
  // プリプロセッサが文字列定数を整数定数として扱えないため、エラーが発生します。
  #if CONSTANT_NAME
  printf("定数はYESです\n");
  #endif
  return 0;
}

この例では、CONSTANT_NAME"YES" として定義され、#if の中で評価される際に整数として認識されません。

プリプロセッサディレクティブの注意点

プリプロセッサディレクティブを使用する際には、以下の点に注意する必要があります。

#if#elif で使用する式は、必ず整数定数式でなければなりません。

・マクロ定義時に、意図した値が適切な型(数値)になっているか確認する必要があります。

・未定義のマクロは自動的に 0 と評価されるため、意図しない条件分岐が発生する可能性がある点にも留意が必要です。

C1017エラーの対処法

正しい定数定義の方法

エラー C1017 を回避するためには、定数を正しく定義することが重要です。

文字列定数が原因の場合、定数を整数値に変更する必要があります。

たとえば、元々 "YES" という文字列で定義していたものを、1 という整数に変更することで、整数定数式として正しく評価されるようになります。

文字列定数から整数定数への変更手順

  1. マクロ定義部分を確認し、文字列定数として定義されている部分を探します。
  2. その文字列定数を、該当箇所で必要な整数値に書き換えます。
  3. 該当する #if#elif のディレクティブが期待する動作となるように、条件式を確認します。

たとえば、以下のように変更します。

元のコード:

#define CONSTANT_NAME "YES"
#if CONSTANT_NAME
// エラー発生
#endif

変更後のコード:

#define CONSTANT_NAME 1
#if CONSTANT_NAME
// 正常に動作
#endif

定義ミスのチェックポイント

定義ミスが原因でエラーが発生していないか、以下のポイントをチェックしてください。

・マクロ名が別の用途で既に使われていないか。

・マクロの定義が意図する型(整数型)になっているか。

・プリプロセッサディレクティブでの式が、期待どおりに評価されるか。

コンパイラオプションによる動作確認

コンパイラには、プリプロセッサの出力結果を確認するためのオプションが用意されています。

これにより、どのようにディレクティブが展開されているかを把握できます。

/P, /E, /EPの使用方法と効果

/P オプション

プリプロセッサの出力をファイルに出力します。

これにより、プリプロセス後のコードが確認でき、定数の展開状況が把握できます。

/E オプション

プリプロセッサの結果を標準出力に出力するため、直接確認することができます。

/EP オプション

プリプロセッサの結果をファイルに保存し、かつソースコードの行番号の情報を含めずに出力するため、読みやすい形式となります。

これらのオプションを活用することで、どの部分が問題となっているのかを詳細に確認することができ、エラーの原因究明に役立ちます。

実践的なコード例

修正前のコード詳細

以下は、エラー C1017 が発生する修正前のコード例です。

CONSTANT_NAME が文字列定数として定義されているため、#if での評価時にエラーが発生します。

#include <stdio.h>
#define CONSTANT_NAME "YES"  // 文字列定数として定義
int main(void) {
  // プリプロセッサが文字列定数を整数定数として評価できずエラーとなる
  #if CONSTANT_NAME
  printf("定数はYESです\n");
  #endif
  return 0;
}

修正後のコード事例

下記は、修正後のコード例です。

CONSTANT_NAME を整数値 1 として定義することで、#if で適切に評価され、エラーが解消されます。

#include <stdio.h>
#define CONSTANT_NAME 1  // 整数定数として定義
int main(void) {
  // 正常に整数定数として評価され、条件が成立する
  #if CONSTANT_NAME
  printf("定数は1です\n");
  #endif
  return 0;
}

コードの比較と解説

・修正前

CONSTANT_NAME"YES" と定義され、文字列定数として扱われるため、#if CONSTANT_NAME で整数定数式として評価できません。

・修正後

CONSTANT_NAME1 として定義することで、#if CONSTANT_NAME の評価が正常に行われ、条件が成立します。

コンパイル結果の確認ポイント

修正後のコードは、以下のポイントで確認してください。

・コードのコンパイル時にエラー C1017 が発生しないこと。

・実行時に printf の出力が正しく表示されること。

修正後のコードをコンパイルして実行すると、コンソールには以下のような出力が得られます。

定数は1です

まとめ

本記事では、C1017エラーの原因とその対応方法を解説しました。

プリプロセッサで使用する式は整数定数式でなければならず、文字列定数が定義されるとエラーが発生することを説明しています。

定数定義の見直し、チェックポイントの確認、コンパイラオプションの利用方法に触れ、サンプルコードで修正前後の違いを示しました。

この記事を通して、エラー回避のための具体的な手法が理解できます。

関連記事

Back to top button
目次へ