4

I want to know how scanf function is implemented. (Just for fun of course) Number of arguments is variable, so it's certainly implemented by va_list, va_arg macros.

It also throws some warnings, when number of arguments does not match with format string. This could be done by parsing format string and comparing it with number of arguments. No magic.

The only thing that I can't see how implemented, is type checking. When type of an argument (pointer to a data) does not match corresponding declaration in format literal, scanf produces a warning. How can one check type of data that a pointer points to?

Example:

#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
}

Output:

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

AFAIK the C library is not a part of C language/Compiler, so there is nothing language-related in <stdio.h>. I'm assuming the warning is produced by implementation of scanf, not by compiler [?]. (Maybe using #warning)

If I want to do something similar in some code, how do I know which data type a pointer is pointing to?

Note: I have downloaded source code of GNU C library and looked at scanf.c. I can't find my way through the very complicated code. There is a lot of #ifndef s and calls to other functions with strange names and structure...

4

2 回答 2

3

此检查由 gcc 编译器处理,特别是针对 scanf/printf 函数。

这是一个非常常见的错误,值得为这些函数在编译器中添加特殊情况代码。

在此处查看 GCC -WFormat 标志:http: //gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html

-Wformat :检查对 printf 和 scanf 等的调用,以确保提供的参数具有适合指定格式字符串的类型,并且格式字符串中指定的转换有意义。这包括 printf、scanf、strftime 和 strfmon(X/Open 扩展,不在 C 标准中)系列中的标准函数和格式属性指定的其他函数(请参阅函数属性)。

并非所有编译器都实现了这些检查,因此它当然不是可以依赖的。

使用 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为 a double,所以它知道&x是 a double*。然后它扫描格式字符串并看到格式需要一个int*那里,因此它发出警告。

于 2012-10-15T13:15:53.490 回答