4

scanf関数がどのように実装されているか知りたいです。(もちろん楽しみのために)引数の数は可変であるためva_listva_argマクロによって確実に実装されます。

また、引数の数がフォーマット文字列と一致しない場合、いくつかの警告がスローされます。これは、フォーマット文字列を解析し、それを引数の数と比較することで実行できます。魔法はありません。

どのように実装されているかわからないのは、型チェックだけです。引数の型(データへのポインタ)がフォーマットリテラルの対応する宣言と一致しない場合scanf、警告が生成されます。ポインタが指すデータの種類をどのように確認できますか?

例:

#include<stdio.h>
int main()
{
    char buffer1[32], buffer2[32];
    int n; 
    double x;
    scanf("%s %s %d",buffer1, buffer2, &x); // warning
    scanf("%s %s %d",buffer1, buffer2, &n); // ok
}

出力:

warning: format ‘%d’ expects argument of type ‘int *’,
but argument 4 has type ‘double *’ [-Wformat]

AFAIK CライブラリはC言語/コンパイラの一部ではないため、に言語関連のものはありません<stdio.h>。警告はscanf、コンパイラ[?]ではなく、の実装によって生成されると思います。(多分使用#warning

あるコードで同様のことをしたい場合、ポインターが指しているデータ型をどのように知ることができますか?

:GNU Cライブラリのソースコードをダウンロードして、を確認しましたscanf.c。非常に複雑なコードを見つけることができません。#ifndef奇妙な名前と構造を持つ他の関数へのsと呼び出しがたくさんあります...

4

2 に答える 2

3

このチェックは、特にscanf/printf関数のgccコンパイラによって処理されます。

これは非常に一般的なエラーであるため、これらの関数のコンパイラに特殊なケースのコードを追加する価値があります。

ここでGCC-WFormatフラグを参照してください:http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html

-Wformat:printfやscanfなどの呼び出しをチェックして、指定された引数が指定されたフォーマット文字列に適切な型であり、フォーマット文字列で指定された変換が意味をなすことを確認します。これには、printf、scanf、strftime、およびstrfmon(C標準ではなくX / Open拡張機能)ファミリの標準関数、およびフォーマット属性(関数属性を参照)で指定されたその他の関数が含まれます。

これらのチェックはすべてのコンパイラーによって実装されているわけではないので、確かに信頼できるものではありません。

GCCでは、関数属性'format'および'format-arg'を使用して、関数に同じチェックを適用するようにコンパイラーに指示できます。

format(archetype、string-index、first-to-check)format属性は、関数がprintf、scanf、strftime、またはstrfmonスタイルの引数を取り、フォーマット文字列に対して型チェックする必要があることを指定します。たとえば、宣言:

extern int my_printf (void *my_object, const char *my_format, ...)  
 __attribute__ ((format (printf, 2, 3)));

...コンパイラがmy_printfの呼び出しの引数をチェックして、printfスタイルのフォーマット文字列引数my​​_formatとの整合性を確認します。

于 2012-10-15T13:17:16.343 に答える
2

警告はコンパイラによって生成されます。あなたはとして宣言xしたdoubleので、それはであることがわかり&xますdouble*。次に、フォーマット文字列をスキャンし、フォーマットにint*そこが必要であることを確認して、警告します。

于 2012-10-15T13:15:53.490 に答える