Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the C Standard allow this code to compile without errors? [closed]

Here is a piece of code that seems to be accepted without errors:

#include <stdio.h>
#include <string.h>

int main() {
    if (strcmp(1, 2))
        printf(3);
}

Compiling with clang -std=c11 -Weverything does produce 4 warnings:

badstrcmp.c:5:16: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'const char *' [-Wint-conversion]
    if (strcmp(1, 2))
               ^
/usr/include/string.h:77:25: note: passing argument to parameter '__s1' here
int      strcmp(const char *__s1, const char *__s2);
                            ^
badstrcmp.c:5:19: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'const char *' [-Wint-conversion]
    if (strcmp(1, 2))
                  ^
/usr/include/string.h:77:43: note: passing argument to parameter '__s2' here
int      strcmp(const char *__s1, const char *__s2);
                                              ^
badstrcmp.c:6:16: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'const char *' [-Wint-conversion]
        printf(3);
               ^
/usr/include/stdio.h:259:36: note: passing argument to parameter here
int      printf(const char * __restrict, ...) __printflike(1, 2);
                                       ^
badstrcmp.c:6:16: warning: format string is not a string literal (potentially insecure) [-Wformat-security]
        printf(3);
               ^
badstrcmp.c:6:16: note: treat the string as an argument to avoid this
        printf(3);
               ^
               "%s",
4 warnings generated.

My question is Why does the C Standard allow it to compile?. This kind of problems should be diagnosed as errors and the code should be refused. Why does the C Standard allow the program to be translated?

like image 615
chqrlie Avatar asked Feb 11 '17 18:02

chqrlie


2 Answers

Your question seems to be based on an invalid premise that C Standard somehow "allows this code to compile". In reality C Standard does not have such concept as "allowing or not allowing the code to compile".

If the code is invalid, the Standard requires compilers to tell you about that through diagnostic messages. The Standard does not require compilers to refuse to compile your code. They can still go ahead and compile it in some implementation-defined way.

Your code is blatantly invalid according to C Standard. Standard C language does not allow implicit integer to pointer conversions. And your compiler clearly told you about that through diagnostic messages. This is enough for the compiler to meet the Standard's requirements.

After that all bets are off. Your compiler might compile it into "something", but this is not a conforming C program. Its behavior is not defined by the language.

As for the format of diagnostic messages you receive (and whether they are "warnings" or "errors") - it is a question to your compiler. In C it is a Quality of Implementation issue. C Standard has nothing to do with it.

You can ask clang to report C language constraint violations as "errors" by supplying a -pedantic-errors flag. It is not perfect for that purpose, but it will make compiler to refuse compiling your code (if that's what you want).

like image 85
AnT Avatar answered Sep 27 '22 19:09

AnT


and the code should be refused.

Well that's a big assumption.

To actually quote the standard:

an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated. It may also successfully translate an invalid program.

(5.1.1.3 note 9)

The standard does not place significant limitations on what a compiler has to do when an error is encountered, precisely for the reason that in many situations and on many platforms, "errors" may actually be well-defined (by the implementation) extension behaviours. It may also be better, from the perspective of providing useful information to the developer, to continue translating and pick up other errors or information in the following part of the program, than to give up at the first incredibly minor, still-syntactically-valid difficult point.

It also prefers not to make too many assumptions about what exactly "translation" involves (translation phase 7 is basically just "something happens here"). There are no notions of "machine code" (excluding extensions like J.5.7) in the strictly standard version of the language, for instance, so the standard cannot prohibit a compiler from emitting it.

like image 35
Leushenko Avatar answered Sep 27 '22 18:09

Leushenko