8

私が書いている小さな C ライブラリには、エラー報告機能があります。errorf単純なerror関数に加えて、エラー メッセージに簡単に情報を埋め込むことができる関数を提供したいと考えています。

/*
 * Prints a formatted error message. Use it as you would use 'printf'. See the
 * 'sio_error' function.
 */
void sio_errorf(const char *format, ...) {
    // Print the error prefix                           
    if (g_input == STDIN) fputs("error: ", stderr);
    else fprintf(stderr, "%s: ", g_progname);

    // Pass on the varargs on to 'vfprintf'. 
    va_list arglist;
    va_start(arglist, format);
    // This may produce the following warning -- ignore it:
    //     warning: format string is not a string literal
    vfprintf(stderr, format, arglist);
    va_end(arglist);
    fputc('\n', stderr);
}

-Weverything問題は、次の警告が表示されることです (スイッチを使用して clang 4.0 でコンパイル):

警告: フォーマット文字列は文字列リテラルではありません

なぜこれを行うのが悪いのか理解しています。この警告を取り除く方法はありますか? 引数が常に文字列リテラルであることをコンパイラが認識できるように、format引数を文字列リテラルにすることはできますか?sio_errorf

を使用できることはわかっています-Wno-format-nonliteralが、他の人が手動でコンパイルする場合にのみ、そうしません。警告を黙らせるソースコードの何かが欲しいです。

理想的には、渡した文字列がsio_errorf 実際にリテラルでない場合でも警告が表示されますが、それが可能かどうかはわかりません。

4

2 に答える 2

13

GCC またはその親戚の 1 つを使用している場合は、宣言の属性を試してください。

void sio_errorf(const char *format, ...) __attribute__((format(printf, 1, 2)));

属性を定義に追加するには、これを使用できます。

__attribute__((format(printf, 1, 2)))
    static void sio_errorf(const char *format, ...) {
      ....
于 2012-08-29T05:07:04.487 に答える
10

多くのコンパイラでは、何らかの方法で警告レベルを設定できます。たとえば、gcc では、-Wコンパイラを呼び出すときに、コマンド ラインのフラグを介して制御できます。

うまくいけば、次のようなプログラムから使用しているコンパイラです。

#include <stdio.h>
int main (void) {
    char *s = "xyzzy\n";
    printf (s);
    return 0;
}

説明した正確なメッセージを生成します ( と で警告を有効にした-Wformatと仮定します-Wformat-nonliteral)。

探している特定のコマンド ライン引数は次のとおりです。

-Wno-format-nonliteral

これにより、これらの関数で非リテラル文字列を使用することについての苦情を防ぐことができます。

ただし、プラグマを使用してコードで特定の診断メッセージの処理をオンザフライで指定できるように、よりきめ細かいものを探している場合があります。

#include <stdio.h>
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
int main (void) {
    char *s = "xyzzy\n";
    printf (s);
    return 0;
}
#pragma GCC diagnostic warning "-Wformat-nonliteral"

これを でコンパイルすると-Wformat -Wformat-nonliteral、関数の特定の警告を無視するように gcc に指示したため、警告は表示されませんmain

私が実行したものより新しいバージョンの gcc には、次のオプションがあります。

#pragma GCC diagnostic push
#pragma GCC diagnostic pop

これにより、診断の状態がプッシュおよびポップされます。これにより、上記のコードでその警告をエラーとして構成する可能性がある問題が回避されます.2番目のプラグマはそれを警告に変更します.

プッシュ/ポップを使用すると、次のような元の配置に復元できます。

#include <stdio.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
int main (void) {
    char *s = "xyzzy\n";
    printf (s);
    return 0;
}
#pragma GCC diagnostic pop
于 2012-08-29T05:11:21.000 に答える