cc-libraries

Runtime typechecking for pointers


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...


Solution

  • This check is handled by the gcc compiler, specifically for scanf/printf functions.

    It's such a common error that it's worth adding special case code to the compiler for these functions.

    see the GCC -WFormat flag here: http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Warning-Options.html

    -Wformat : Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense. This includes standard functions, and others specified by format attributes (see Function Attributes), in the printf, scanf, strftime and strfmon (an X/Open extension, not in the C standard) families.

    These checks are not implemented by all compilers, so it's certainly not something to rely on.

    With GCC you can use Function Attributes 'format' and 'format-arg' to tell the compiler to apply the same checks to your functions.

    format (archetype, string-index, first-to-check) The format attribute specifies that a function takes printf, scanf, strftime or strfmon style arguments which should be type-checked against a format string. For example, the declaration:

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

    ...causes the compiler to check the arguments in calls to my_printf for consistency with the printf style format string argument my_format.