2

printf次の引数を取る-like関数を作成しました。

  • 1つの必須の引数(カスタムエラーコード)
  • オプションのフォーマット文字列
  • フォーマット引数の可変カウント

関数プロトタイプは次のようになります。

int my_printf(int err_code, ...);

err_codeフォーマット文字列(および可能なフォーマットタグ)が指定されているかどうかの情報も含まれます。

それらが指定されている場合は、関数を使用してフォーマット文字列を抽出し、残りの引数と一緒にva_arg渡すことができます。vfprintf

呼び出しは次のようになります。

my_printf(-ERR_SIMPLE);
my_printf(-ERR_COMPLICATED, "Error: problem with %d", 123);

残念ながら、フォーマットタイプチェックにGCC属性を使用することはできません。これには、 string-index:が必要なためです。

フォーマット(アーキタイプ、文字列インデックス、最初にチェック)

とにかくタイプチェックを行うことはまだ可能ですか?ヘルパーマクロ、ヘルパー関数、オプションのフォーマット文字列部分の変更などを使用したソリューションは許容されます。

更新:va_list変更された関数を-like関数に 渡すことvfprintfがOKかどうかはわかりません。コメントを参照してください。可能であれば、これを避けて、オプションのフォーマット文字列部分にマクロなどを使用することをお勧めします。

4

1 に答える 1

2

(申し訳ありませんが、あなた試してみたことはありませんでした__attribute__。私の悪いことです)。

ここで説明するように、「引数のカウント」を試してみてください。

http://locklessinc.com/articles/overloading/

ただし、これによりGCCが引数チェックを選択的に適用できるかどうかはわかりません。しかし、そうすべきだと思います。

#defineハックを追加して、機能しているように見える更新:

#include <stdio.h>

int printf_1(int err)
{
        printf("Got error %d\n", err);
        return 0;
}

int printf_2(int error, char *string)
{
        printf("Error %d and message %s\n", error, string);
        return 0;
}

int printf_3(int error, char *fmt, ...) __attribute__ ((format (printf, 2, 3)));

int printf_3(int error, char *fmt, ...)
{
        printf("Received full string err=%d, fmt=%s\n", error, fmt);
        return 0;
}

#define printf_4        printf_3
#define printf_5        printf_3
#define printf_6        printf_3
#define printf_7        printf_3
#define printf_8        printf_3
#define printf_9        printf_3
#define printf_10       printf_3


#define COUNT_PARMS2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _
#define COUNT_PARMS(...)\
        COUNT_PARMS2(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

#define CAT(A, B) CAT2(A, B)
#define CAT2(A, B) A ## B

#define myprintf(...)\
        CAT(printf_, COUNT_PARMS(__VA_ARGS__))(__VA_ARGS__)

int main()
{
        myprintf(19);
        myprintf(19, "Hello");
        myprintf(19, "Hello '%s'", "world");
        // Warning!
        myprintf(19, "Hello '%s'", "world", 42);
        myprintf(19, 42);
        return 0;
}

私は正しく受け取ります(gcc 4.6.2):

$ gcc -W -Wall -o test test.c

test.c: In function ‘main’:
test.c:48:2: warning: too many arguments for format [-Wformat-extra-args]
test.c:49:2: warning: passing argument 2 of ‘printf_2’ makes pointer from integer without a cast [enabled by default]
test.c:9:5: note: expected ‘char *’ but argument is of type ‘int’
于 2012-09-12T13:47:01.267 に答える