C grammar compound statement [duplicate] - c

This question already has answers here:
Why was mixing declarations and code forbidden up until C99?
(6 answers)
Closed 8 years ago.
I was looking at the C grammer on K&R and i found this:
compound-statement:
{ declaration-list opt statement-list opt }
declaration-list:
declaration
declaration-list declaration
statement-list:
statement
statement-list statement
Which means that we can't have declarations after statements. However i am doing this really often like:
#include <stdio.h>
int main()
{
printf("Lets use a new block");
{
int a=1;
printf("%d",a);
int b=3;
printf("%d",b);
}
return 0;
}
This code compiles with no warning and no errors. Am i not understanding the grammar correctly?

To get the error you want, pass these flags to gcc:
-std=c90 -pedantic-errors
GNU extensions, as well as more recent C standards, allow declarations after other statements in a scope.

You understand the grammar fine. However, C has advanced since the K&R days and now the grammar accepts interleaved declarations and statements.

Related

Why still compile successfully and got a.out after warning: implicit declaration of function? [duplicate]

This question already has answers here:
Implicit function declarations and linkage
(4 answers)
Closed 2 years ago.
Is it necessary to declare a variable before using it if the compilation works anyway ?
/* hello-world.c */
#include <stdio.h>
int main(void) {
printf("Hello World!\n");
printf("1 + 2 is: %d\n", sum(1, 2));
return 0;
}
/* sum.c */
int sum(int a, int b) {
return a + b;
}
I compile these code with gcc hello-world.c sum.c and clang hello-world.c sum.c,
both got a warning: implicit declaration of function 'sum' but compiled the a.out.
Is there any case proving it's absolutely necessary to declare before using in C?
(edit: Here, i mean the function prototype, if there is any confusion)
"proving" with C is done by the C Standard, not by observation of compilers. Because the standard leaves a lot of things up to compiler discretion .
This program was valid in C89 but is not valid in C99 and later (in which undeclared identifiers cannot be used in expressions).
What the compiler chooses to do with non-compliant programs is up to that compiler, except that some violations (including this one) must result in a diagnostic being printed. Perhaps your compiler opts to print the diagnostic and then go on to behave like C89 .
The classical case is incompatible implicit declaration:
// a.c
int f()
{
return g();
}
// b.c
float g() { return 3.14; }
In this case, it is undefined behavior.

Function declaration not needed when compiling two C files [duplicate]

This question already has answers here:
Is implicit function declaration legal in C89?
(2 answers)
Implicit function declarations in C
(6 answers)
What is the default C -std standard version for the current GCC (especially on Ubuntu)?
(7 answers)
Closed 3 years ago.
I was trying to simultaneously compile the following C files
file1.c
#include<stdio.h>
int main()
{
foo();
return 0;
}
file2.c
#include<stdio.h>
void foo()
{
printf("Hello");
}
I compiled the two files using the following command in linux
gcc file1.c file2.c -o file
It compiled successfully without any warnings and on running it gave the output as 'Hello'
Shouldn't file1.c require a prototype like void foo(). Is there anything in the C standard regarding this ?
Before C99, C had a thing called implicit declaration that allowed you to do that.
If you didn't specify a declaration for foo and you called foo, it was implicitly declared as int foo();.
This, however, was removed from C99 and subsequent standards.

C function declaration with variable after signature [duplicate]

This question already has answers here:
Alternative (K&R) C syntax for function declaration versus prototypes
(5 answers)
Closed 5 years ago.
I was going through the make program's source code and I came across the following function declaration:
struct dep *
read_all_makefiles (makefiles)
char **makefiles;
{ ... followed by function code ...
How do we decipher this declaration?
It's the old K&R style of function parameter declaration, prior to the ANSI/ISO standard C. This style is outdated now but can still be found in some very old codes. Although it's still in standard, it's recommended not to write like this anymore.
To decipher, simply move the parameter declaration list back to the function prototype, one-by-one, with the identifiers matching.
Quoting draft N1570, ยง6.9.1/13:
EXAMPLE 1
extern int max(int a, int b)
{
return a > b ? a : b;
}
EXAMPLE 2
extern int max(a, b)
int a, b;
{
return a > b ? a : b;
}
See Alternative (K&R) C syntax for function declaration versus prototypes

gcc compiles with no error with no return type (even using -Wall) [duplicate]

This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 6 years ago.
I'm wondering why gcc doesn't display an error while compiling, even while using the -Wall option. Also tried the -std=c89 option.
Here's the code:
#include <stdio.h>
int main(void)
{
printf("hello, world\n");
}
Sorry if this post is a duplicate but couldn't find a case where this option is being used.
Thanks!
In C++ and C99 and later, hitting the end of main() without returning a value is equivalent to returning 0. In earlier versions of the C standard it's undefined behavior which the compiler isn't obliged to issue a diagnostic for, although in practice GCC's likely doing an implicit return 0; just as it would for C++ or C99 onwards.
See What should main() return in C and C++? for a lot more detail.

Declare C89 local variables in the beginning of the scope?

I was trying to do this in ANSI C:
include <stdio.h>
int main()
{
printf("%d", 22);
int j = 0;
return 0;
}
This does not work in Microsoft Visual C++ 2010 (in an ANSI C project). You get an error:
error C2143: syntax error : missing ';' before 'type'
This does work:
include <stdio.h>
int main()
{
int j = 0;
printf("%d", 22);
return 0;
}
Now I read at many places that you have to declare variables in the beginning of the code block the variables exist in. Is this generally true for ANSI C89?
I found a lot of forums where people give this advice, but I did not see it written in any 'official' source like the GNU C manual.
ANSI C89 requires variables to be declared at the beginning of a scope. This gets relaxed in C99.
This is clear with gcc when you use the -pedantic flag, which enforces the standard rules more closely (since it defaults to C89 mode).
Note though, that this is valid C89 code:
include <stdio.h>
int main()
{
int i = 22;
printf("%d\n", i);
{
int j = 42;
printf("%d\n", j);
}
return 0;
}
But use of braces to denote a scope (and thus the lifetime of the variables in that scope) doesn't seem to be particularly popular, thus C99 ... etc.
Now I read at many places that you have to declare variables in the beginning of the code block the variables exist in. Is this generally true for ANSI C 89?
Yes, this is required in the syntax of a compound statement in the C89/C90 Standard:
(C90, 6.6.2 Compound statement, or block)
Syntax
compound-statement
{ declaration-list_opt statement-list_opt }
Declaration have to be before statements in a block.
C99 relaxed this by allowing mixing of declarations and statements in a block. In the C99 Standard:
(C99, 6.8.2 Compound statement)
Syntax
compound-statement:
{ block-item-list_opt }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration
statement
This is absolutely true for C89. (You're better off looking at documentation for the language, e.g., books and standards. Compiler documentation usually only documents differences between the language the compiler supports and ANSI C.)
However, many "C89" compilers allow you to put variable declarations nearly anywhere in a block, unless the compiler is put in a strict mode. This includes GCC, which can be put into a strict mode with -pedantic. Clang defaults to a C99 target, so -pedantic won't affect whether you can mix variable declarations with code.
MSVC has rather poor support for C, I'm afraid. It only supports C89 (old!) with a few extensions.

Resources