Declare C89 local variables in the beginning of the scope? - c

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.

Related

Newbie question about C variable declarations

I'm reading an introducty book about C and I came across the following paragraph:
But the following code compiles with expected output:
#include <stdio.h>
int main()
{
for(int i = 0; i<=10; i++)
{
int val = i + 1;
int x = val * val;
printf("%d\n", x);
int y = x;
}
return 0;
}
I use https://www.onlinegdb.com/ and in the above code I declared many variables after the first executable statement. And this is to me does not match what the section from the book tells.
Am I misunderstanding what the book is telling?
In strictly conforming C 1990, declarations could appear only at file scope (outside of function definitions) or at the start of a compound statement. The grammar for a compound statement in C 1990 6.6.2 was:
compound-statement
    { declaration-listopt statement-listopt }
That says a compound statement is { followed by zero or more declarations, then zero or more statements, then }. So the declarations had to come first.
In C 1999 6.8.2, this changed to:
compound-statement
    { block-item-listopt }
A block-item-list is a list of block-item, each of which may be a declaration or a statement, so declarations and statements could be freely mixed.
In your example, the declarations int val = i + 1; and int x = val * val; do not appear after executable statements in their compound statement. The compound statement starts with the { immediately before int val = i + 1;, so that declaration is at the start of the compound statement.
Another change was that the for grammar was changed from this in C 1990 6.6.5:
for ( expressionopt ; expressionopt ; expressionopt ) statement
to this choice of two forms in C 1999 6.8.5:
for ( expressionopt ; expressionopt ; expressionopt ) statement
for ( declaration expressionopt ; expressionopt ) statement
(Note the declaration includes a terminating ;.)
That explains why you can have int i = 0 in for(int i = 0; i<=10; i++).
The book is referring to the original C specification from over 30 years ago known as "ANSI C" or "C89" or "C90". If we run a C compiler in C89 mode, -std=c89, we get a warning from your code...
cc -Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c89 -pedantic -g -fsanitize=address -c -o test.o test.c
test.c:5:9: warning: variable declaration in for loop is a C99-specific feature [-Wc99-extensions]
for(int i = 0; i<=10; i++)
^
test.c:5:9: warning: GCC does not allow variable declarations in for loop initializers before C99 [-Wgcc-compat]
2 warnings generated.
C99, the update to C made in 1999, made this untrue. Running your code with -std=c99 gives no warning. C99 made this and other impactful changes to the language, like // comments.
There is also C11 and the latest stable version of C is C17, but compiler support for both is spotty.
Why is this book referring to such an old version of the language? C has existed since 1978 and there are a lot of old code and old compilers out there. C Compilers have been very slow to fully adopt new standards making authors quite conservative. A big stumbling block was Microsoft Visual C++ did not implement C99 until 2013! So ANSI C was the lowest-common denominator for a very long time.
In recent years, C compilers have gotten better about standards compliance, so you can rely on C99 (which is old enough to drink) as your baseline.
All variables in your example have been declared before used.
The declarations are:
int i ...;
int val ...;
int x ...;
Note that all declarations happen before the first function call in the corresponding block. On other words: i, val and x are all declared before the printf.
As stated in the comments: Some old books might refer to old versions of C. The variable declaration within the for loop came with C99 for example. Beginning with C99 you could also declare variables in the middle of the block. So you are allowed to declare some int y; after the printf and your code would still compile.

In C why the parameter passed to a void function is compiled while it has to throw an error

#include<stdio.h>
void fun(z)
{
printf("%d",z);
}
int main()
{
int a=5;
fun(a);
}
This is giving output as 5. Shouldn't it give an error - undeclared variable z ?
Is this a compiler optimization ?
This is not a compiler optimization, it is a compliance with an ancient C convention that allowed you to skip variable and parameter types when the desired type is int. This convention pre-dates the ANSI standard, and should be avoided even if your compiler is fine with such code.
You will get a warning if you tell the compiler that you want your code to comply with one of more modern standards, say, C99 or C11. The flag is compiler-dependent. If you are using gcc, add
-std=c99
flag to see the warning.

for loop initial declaration error

In my code I can't initialize variables in for loop initialization part.
When I write this code:
long unsigned int arr[3][3];
char str[50];
for(;gets(str);)
{
int temp=0;
for(int i,j,k=0; str[k]!='\0'; k++){ if(str[k]!=' ')temp=temp*10+(str[k]-48);
the compiler shows
error: 'for' loop initial declarations are only allowed in c99 mode
I have no idea what that means,
but if I write my code like this:
long unsigned int arr[3][3];
char str[50];
for(;gets(str);)
{
int temp=0;
int i,j,k=0;
for(; str[k]!='\0'; k++){ if(str[k]!=' ')temp=temp*10+(str[k]-48);
it works fine.
Why is this happening?
Declaring variables in loops like
for (int i = 0; ...; ...)
was new in the C99 standard, and wasn't allowed in the earlier standards. What the error message tells you is that your compiler is set up to compile using an earlier standard, and so you can't use declarations inside for statements.
You either have to remove the declaration from inside the for statement, or tell the compiler to use a later standard when compiling. Telling the compiler to use a later version can be done by adding the flag -std=c99 if you have GCC or clang.
You are using a compiler that only supports C89, or the compiler is in the mode that supports C89 only. The declarations of variables must in the beginning of a block in C89. It's not a limit anymore in C99 or C++.
Change to C99 mode or put the declaration of i,j,k in the beginning of the block. The way you initialize them looks incorrect, you only initialized k.
for(;gets(str);)
{
int temp=0;
int i,j,k;
for(i=0,j=0,k=0; str[k]!='\0'; k++){ if(str[k]!=' ')temp=temp*10+(str[k]-48);
And don't use gets, it's dangerous, use fgets instead.
This happens because your former code does not obey the C standard under which you compile the code. Check the manual of your C (or C++) compiler how to turn on (if possible) the compilation under the C99 standard. For GNU compiler it is -std=c99 switch.

Can't comment // on codeblocks

I'm using codeblocks to learn C programming.
When I use /* */ the program works, but when I use // the program returns this error.
expected identifier or ‘(’ before ‘/’ token|
here's the main.c
#include <stdio.h>
#include <stdlib.h>
//Ex1
int i;
float p;
char *n;
int main(void)
{
i = 22;
p = 70.0;
n = "Samuel";
printf("%s %d %.2f", n, i, p);
return 0;
}
From wiki:
C++ style line comments start with // and extend to the end of the line. This style of comment originated in BCPL and became valid C syntax in C99; it is not available in the original K&R C nor in ANSI C:
If you use gcc compiler, then add -std=c99 compiler argument.
It will enables C99 features, like // comments.
If you have -ansi option, then remove it.
Four major versions of the C language exist:
ISO 9899:2011. The current standard, known as C11. Allows //.
ISO 9899:1999. An obsolete standard, known as C99. Allows //.
ISO 9899:1990. An obsolete standard, known as C90, or sometimes C89. Does not allow //.
Pre-standardization. Known as "K&R C". Does not allow //.
Make sure to use a modern compiler with support for the relevant standard. Today, you should demand that a C compiler at least conforms with C99.

C: for loop int initial declaration

Can someone elaborate on the following gcc error?
$ gcc -o Ctutorial/temptable.out temptable.c
temptable.c: In function ‘main’:
temptable.c:5: error: ‘for’ loop initial declaration used outside C99 mode
temptable.c:
...
/* print Fahrenheit-Celsius Table */
main()
{
for(int i = 0; i <= 300; i += 20)
{
printf("F=%d C=%d\n",i, (i-32) / 9);
}
}
P.S: I vaguely recall that int i should be declared before a for loop. I should state that I am looking for an answer that gives a historical context of C standard.
for (int i = 0; ...)
is a syntax that was introduced in C99. In order to use it you must enable C99 mode by passing -std=c99 (or some later standard) to GCC. The C89 version is:
int i;
for (i = 0; ...)
EDIT
Historically, the C language always forced programmers to declare all the variables at the begin of a block. So something like:
{
printf("%d", 42);
int c = 43; /* <--- compile time error */
must be rewritten as:
{
int c = 43;
printf("%d", 42);
a block is defined as:
block := '{' declarations statements '}'
C99, C++, C#, and Java allow declaration of variables anywhere in a block.
The real reason (guessing) is about allocating internal structures (like calculating stack size) ASAP while parsing the C source, without go for another compiler pass.
Before C99, you had to define the local variables at the start of a block. C99 imported the C++ feature that you can intermix local variable definitions with the instructions and you can define variables in the for and while control expressions.

Resources