Why do I have to specify data type each time in C?

后端 未结 11 2724
温柔的废话
温柔的废话 2020-12-12 18:17

As you can see from the code snippet below, I have declared one char variable and one int variable. When the code gets compiled, it must identify t

相关标签:
11条回答
  • 2020-12-12 18:21

    GCC (and possibly other C compilers) keep track of argument types, at least in some situations. But the language is not designed that way.

    The printf function is an ordinary function which accepts variable arguments. Variable arguments require some kind of run-time-type identification scheme, but in the C language, values do not carry any run time type information. (Of course, C programmers can create run-time-typing schemes using structures or bit manipulation tricks, but these are not integrated into the language.)

    When we develop a function like this:

    void foo(int a, int b, ...);
    

    we can pass "any" number of additional arguments after the second one, and it is up to us to determine how many there are and what are their types using some sort of protocol which is outside of the function passing mechanism.

    For instance if we call this function like this:

    foo(1, 2, 3.0);
    foo(1, 2, "abc");
    

    there is no way that the callee can distinguish the cases. There are just some bits in a parameter passing area, and we have no idea whether they represent a pointer to character data or a floating point number.

    The possibilities for communicating this type of information are numerous. For example in POSIX, the exec family of functions use variable arguments which have all the same type, char *, and a null pointer is used to indicate the end of the list:

    #include <stdarg.h>
    
    void my_exec(char *progname, ...)
    {
      va_list variable_args;
      va_start (variable_args, progname);
    
      for (;;) {
         char *arg = va_arg(variable_args, char *);
         if (arg == 0)
           break;
         /* process arg */
      }
    
      va_end(variable_args);
      /*...*/
    }
    

    If the caller forgets to pass a null pointer terminator, the behavior will be undefined because the function will keep invoking va_arg after it has consumed all of the arguments. Our my_exec function has to be called like this:

    my_exec("foo", "bar", "xyzzy", (char *) 0);
    

    The cast on the 0 is required because there is no context for it to be interpreted as a null pointer constant: the compiler has no idea that the intended type for that argument is a pointer type. Furthermore (void *) 0 isn't correct because it will simply be passed as the void * type and not char *, though the two are almost certainly compatible at the binary level so it will work in practice. A common mistake with that type of exec function is this:

    my_exec("foo", "bar", "xyzzy", NULL);
    

    where the compiler's NULL happens to be defined as 0 without any (void *) cast.

    Another possible scheme is to require the caller to pass down a number which indicates how many arguments there are. Of course, that number could be incorrect.

    In the case of printf, the format string describes the argument list. The function parses it and extracts the arguments accordingly.

    As mentioned at the outset, some compilers, notably the GNU C Compiler, can parse format strings at compile time and perform static type checking against the number and types of arguments.

    However, note that a format string can be other than a literal, and may be computed at run time, which is impervious to such type checking schemes. Fictitious example:

    char *fmt_string = message_lookup(current_language, message_code);
    
    /* no type checking from gcc in this case: fmt_string could have
       four conversion specifiers, or ones not matching the types of
       arg1, arg2, arg3, without generating any diagnostic. */
    snprintf(buffer, sizeof buffer, fmt_string, arg1, arg2, arg3);
    
    0 讨论(0)
  • 2020-12-12 18:24

    printf is not an intrinsic function. It's not part of the C language per se. All the compiler does is generate code to call printf, passing whatever parameters. Now, because C does not provide reflection as a mechanism to figure out type information at run time, the programmer has to explicitly provide the needed info.

    0 讨论(0)
  • 2020-12-12 18:24

    The first parameter is a format string. If you're printing a decimal number, it may look like:

    • "%d" (decimal number)
    • "%5d" (decimal number padded to width 5 with spaces)
    • "%05d" (decimal number padded to width 5 with zeros)
    • "%+d" (decimal number, always with a sign)
    • "Value: %d\n" (some content before/after the number)

    etc, see for example Format placeholders on Wikipedia to have an idea what format strings can contain.

    Also there can be more than one parameter here:

    "%s - %d" (a string, then some content, then a number)

    0 讨论(0)
  • 2020-12-12 18:25

    Isn't the compiler matured enough to identify that when I declared my variable?

    No.

    You're using a language specified decades ago. Don't expect modern design aesthetics from C, because it's not a modern language. Modern languages will tend to trade a small amount of efficiency in compilation, interpretation or execution for an improvement in usability or clarity. C hails from a time when computer processing time was expensive and in highly limited supply, and its design reflects this.

    It's also why C and C++ remain the languages of choice when you really, really care about being fast, efficient or close to the metal.

    0 讨论(0)
  • 2020-12-12 18:29

    scanf as prototype int scanf ( const char * format, ... ); says stores given data according to the parameter format into the locations pointed by the additional arguments.

    It is not related with compiler, it is all about syntax defined for scanf.Parameter format is required to let scanf know about the size to reserve for data to be entered.

    0 讨论(0)
  • 2020-12-12 18:29

    It is because this is the only way to tell the functions (like printf scanf) that which type of value you are passing. for example-

    int main()
    {
        int i=22;
        printf("%c",i);
        return 0;
    }
    

    this code will print character not integer 22. because you have told the printf function to treat the variable as char.

    0 讨论(0)
提交回复
热议问题