0

私はこれを試しました:

#define format(f, ...) \
                int size = strlen(f) + (sizeof((int[]){__VA_ARGS__})/sizeof(int)) + 1); \
                char *buf = malloc(size); \
                snprintf(buf, size, f, __VA_ARGS__); \
                buf

しかし、多くの構文エラーが返されます。これを正しく行うにはどうすればよいですか?

4

3 に答える 3

3

C マクロは関数ではなく、1:1 置換です。したがって、次のようにマクロを使用する場合:

mystring = format("%d", 5);

あなたはこれを得る:

mystring = int size = strlen(f) + (sizeof((int[]){5})/sizeof(int)) + 1); \
            char *buf = malloc(size); \
            snprintf(buf, size, f, 5); \
            buf;

これは意味がありません。あなたの場合、まともなコンパイラでのパフォーマンスの点でこれ以上悪くならないインライン関数を定義する方が良いでしょう。

本当にマクロである必要があり、GCC を使用している場合、複合ステートメントを使用して目的を達成できます。これにより、mystring = ({ statement1, statement2, ..., statementN})すべてのステートメントがローカル スコープで実行され、次に に割り当てstatementNられmystringます。ただし、コードが移植できなくなり、デバッグが困難になります。

というわけで、実際のアプリケーションでは使用しないでください。

#define format(f, ...) \
    ({ int size = snprintf(NULL, 0, f, __VA_ARGS__) + 1;\
    char * buf = malloc(size);\
    snprintf(buf, size, f, __VA_ARGS__); buf; })

私は真剣です。これを使用しないでください。インライン関数を使用します。va_argandを使用して、通常の関数で可変引数を使用することもできますva_start

inline char * format(f, ...) {
    va_list args;
    va_start(args, f);
    int size = vsnprintf(NULL, 0, f, args) + 1;
    char * buf = malloc(size);
    vsnprintf(buf, size, f, args);
    return buf;
}
于 2012-06-12T15:15:43.427 に答える
0

これを引数なしで使用する場合は、次のように入力する必要があります

snprintf(buf, size, f, ## __VA_ARGS__);

代わりは; それ以外の場合、末尾のコンマは切り捨てられません。

さらに、フォーマット文字列を使用したい場合、それstrlen(format) + length of every other elementsが実際に得られるサイズであるかどうかを確認することはできません。仮定を立ててから、安全な関数を使用する必要があります。

この種のマクロ構文を使用して値を返すこともできません。ただし、GNU 拡張を使用することは可能です。以下の修正された回答を参照してください。

また、やりたいことは

sizeof((int[]){__VA_ARGS__}

? 全然ダメです。可変引数リストのサイズはわかりません。

次のようなことを試してください:

#define format(f, ...) \
            ({
            char *buf = malloc(4096); \
            snprintf(buf, 4096, f , ## __VA_ARGS__); \
            buf
        })

お役に立てれば。

于 2012-06-12T15:13:11.590 に答える
0

最初の行で何をしようとしているのかわかりません。引数の数を計算しようとしているようですが、それを に渡しmalloc、 の戻り値をmallocサイズとして使用しています..?!

スペースを割り当てる正しい方法は、最初にバッファー ポインターとサイズを 0 としてsnprintf呼び出し、戻り値を調べることです。戻り値に 1 を追加すると (null 終了の場合)、割り当てて 2 番目の呼び出しsnprintfに渡す必要があるサイズが得られます。snprintf

また、マクロでこれを実行しようとしないでください。関数と を使用しますvsnprintf

于 2012-06-12T15:14:30.790 に答える