How to compile a C project in C99 mode? - c

I got the following error message while compiling the C code:
error: 'for' loop initial declarations are only allowed in C99 mode
note: use option -std=c99 or -std=gnu99 to compile your code
What does it mean?
How to fix it?

You have done this:
for (int i=0;i<10;i++) {
And you need to change it to this:
int i;
for (i=0;i<10;i++) {
Or, as the error says,
use option -std=c99 or -std=gnu99 to compile your code.
Update copied from Ryan Fox's answer:
gcc -std=c99 foo.c -o foo
Or, if you're using a standard makefile, add it to the CFLAGS variable.

You'll still need C99 if you want to mix statements and variable declarations. As other answers and the error message itself say, add -std=c99 to the command-line when you compile to enable C99 features [1].
But you have always been allowed to write a compound statement (a "block", IOW, but the standard never uses this word!) in place of a single statement.
#include<stdio.h>
int main() {
int i = 5;
{ /* new block, new declarations. */
int i;
for (i=0;i<10;i++){
}
}
printf("%d\n", i); /* prints "5\n" */
}
This is legal in K&R, C90 (aka C89, it's the same thing), and C99.
Enabling C99 mode gets you lots of cool stuff, but it also disables some other cool stuff that gcc allows by default, like anonymous structures and unions within structures and unions.
-std=gnu99 probably enables "all the goodies", but I caution you to avoid doing this. It will make unnecessary difficulty if you (or others) wish to port the code. I'd probably have a windows version of my pet project, ported for free by somebody, had I not done this very thing. It ties you gcc. You don't want to be tied. That's the whole bloody point of standards.

The other answers give you a work around to deal with GCC's default mode. If you'd like to use C99, (which I do recommend in general) then you have to add that compiler flag:
gcc -std=c99 foo.c -o foo
Or, if you're using a standard makefile, add it to the CFLAGS variable.

It means you can't declare variables in for statement.
You should do:
int i ;
for( i = 0 ; i < len ; i++ )
What you are probably doing
for( int i = 0 ; i < len ; i++ )

Related

How to force Werror=declaration-after-statement with -std=c99 in clang

I would like to have compiler throw an error every time there is a declaration after statement because that is the coding style I want to enforce, but I also want to compile with -std=c99 since I use some of the specific c99 features.
The problem is that in c99 declarations are allowed anywhere in the code, not just at the beginning of a block.
Take a look at the following program:
// prog.c
#include <stdio.h>
int main(void)
{
printf("hello world\n");
int i = 0;
return 0;
}
If I compile this code with gcc like this:
gcc -std=c99 -Werror=declaration-after-statement prog.c
it throws the following error:
prog.c: In function ‘main’:
prog.c:6:9: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
6 | int i = 0;
| ^~~
cc1: some warnings being treated as errors
This is the behavior I would like to have when compiling with clang, but clang behaves differently.
If I compile the same code with clang like this:
clang -std=c99 -Werror=declaration-after-statement prog.c
it throws no errors.
Only if I compile the code with clang like this it throws the error I want:
clang -std=c90 -Werror=declaration-after-statement prog.c
prog.c:6:6: error: ISO C90 forbids mixing declarations and code [-Werror,-Wdeclaration-after-statement]
int i = 0;
^
1 error generated.
But this is not good for me because I need to use -std=c99.
Is it possible to force -Werror=declaration-after-statement along with -std=c99 when compiling with clang?
Looking at the source code of clang it seems like not supported.
The diagnostic is defined in clang/include/clang/Basic/DiagnosticSemaKind.td
def ext_mixed_decls_code : Extension<
"ISO C90 forbids mixing declarations and code">,
InGroup<DiagGroup<"declaration-after-statement">>;
And its only usage is in clang/lib/Sema/SemaStmt.cpp
StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr) {
const unsigned NumElts = Elts.size();
// If we're in C89 mode, check that we don't have any decls after stmts. If
// so, emit an extension diagnostic.
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {
// Note that __extension__ can be around a decl.
unsigned i = 0;
// Skip over all declarations.
for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i)
/*empty*/;
// We found the end of the list or a statement. Scan for another declstmt.
for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i)
/*empty*/;
if (i != NumElts) {
Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin();
Diag(D->getLocation(), diag::ext_mixed_decls_code); // <-- here
}
}
...
Note the !getLangOpts().C99 in the if. The diagnose code will never execute with a standard above c90.
Well one thing you can surely try is build clang by yourself and delete that part of the if so end up with if (!getLangOpts().CPlusPlus).
I tried and it worked for me.
You can configure the clang build with cmake -G "Ninja" -DCMAKE_BUILD_TYPE="Release" -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_C_COMPILER="/usr/bin/gcc" -DCMAKE_CXX_COMPILER="/usr/bin/g++" -DLLVM_PARALLEL_LINK_JOBS=2 -DLLVM_OPTIMIZED_TABLEGEN=ON path/to/llvm-project/llvm

Is the form for(int i = 0... a gnu extension? [duplicate]

This question already has answers here:
Where you can and cannot declare new variables in C?
(7 answers)
Closed 4 years ago.
I am working on a computation software written in fortran but I developed a little extension in C. The software have to be higly portable and among other constraints it have to compile on both GCC suite and Intel compiler suite.
I normally test on GCC and everything was going well until I tried to compile with the intel suite. I got an "expected an expression" error on a simple for loop.
I created a minimal test case and it appear that icc refuse to compile the declaration of a variable inside the for loop header.
#include <stdio.h>
int main(int argc, char** argv){
for(int i = 0; i < 5; i++){
printf("%d\n", i);
}
return 0;
}
This give me the following on intel 13, 15, 16, 17 and 18 (but not 19)
$ icc test.c -o ./test
test.c(4): error: expected an expression
for(int i; i < 5; i++){
^
test.c(4): error: identifier "i" is undefined
for(int i; i < 5; i++){
^
compilation aborted for test.c (code 2)
I am not a C specialist but I seen this form of for thousand of times and GCC have never been problem. Is this a GNU extension recently adopted by Intel ?
This is not a GCC extension, you are merely using an old version of the ICC compiler.
Loop iterator declarations inside for loops was added to the standard in the year 1999 (C99). Some older compilers may still default to the oldest C standard C90 and thereby they don't have this feature available. For example, gcc older than 5.0.0 default to "gnu90", which is C90 + extensions. Newer versions default to "gnu11", which is C11 + extensions.
On icc, gcc and clang, this can be solved by always compiling for a specific C standard:
icc -std=c11 -pedantic-errors
For older versions of the mentioned compilers, swap c11 for c99. For very new versions, you can use c17 but it doesn't seem like icc supports that yet.
For more info see What is the difference between C, C99, ANSI C and GNU C?

Telling gcc to fail to compile when in pre-C99 mode

I am giving a lecture on the history of C, and would like to show some idioms that used to be impossible but now are (in particular, defining variables in the middle of the block). I would like to show that older C compilers wouldn't compile it.
gcc has the -std= option for setting the language standard. Unfortunately, setting it for -std=c89 does not produce compilation errors on defining variables in the middle of a block.
I was hoping for a more accurate std version (i.e. - -std=knr), but I could not find any such option.
Am I missing something? Is this a bug in GCC?
gcc (Ubuntu 8.2.0-7ubuntu1) 8.2.0
The code that erroneously compiles:
#include <stdio.h>
int main(argc, argv)
int argc;
char *argv[];
{
printf("Hello, world\n");
int a;
return 0;
}
If you want truly strict conformance to a -std flag, it should be accompanied by the -pedantic-errors flag.
As a demonstration, your code on wandbox with those flags produces:
prog.c: In function 'main':
prog.c:9:9: error: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int a;
^~~

Initialize array in gcc, undefined reference to `memcpy'

I'm coding C in Nachos3.4, Centos 6.0, compile by gcc 2.95.3,
the command line I use is gmake all
when I compile this, everything is fine
int main()
{
char* fname[] = {"c(0)", "c(1)", "c(2)", "c(3)", "c(4)", "c(5)", "c(6)", "c(7)"};
return 0;
}
but when I do this, it said undefined reference to 'memcpy'
int main()
{
char* fname[] = {"c(0)", "c(1)", "c(2)", "c(3)", "c(4)", "c(5)", "c(6)", "c(7)", "c(8)"};
return 0;
}
where is the problem and how can i fix that ?
Your initialisation of the automatic fname array involves the compiler constructing a copy of a large amount of data from a hidden static array to your array on the stack. GCC has several techniques it can use for this, one of it's favourites is to call the C library memcpy routine as this should be nice and quick whatever happens.
In your case you don't seem to have a C library so this is a problem.
You can tell GCC to always use the x86 instructions rather than calling the library like this:
gcc -mstringop-strategy=rep_byte -c -O file.c
or
gcc -mstringop-strategy=loop -c -O file.c
However, I was under the impression that GCC didn't start doing this till somewhere in the mid version 3.x.
Perhaps you're using a 'MIPS' processor, teachers like that processor, in which the required option would be -mno-memcpy.

How do I fix "for loop initial declaration used outside C99 mode" GCC error?

I'm trying to solve the 3n+1 problem and I have a for loop that looks like this:
for(int i = low; i <= high; ++i)
{
res = runalg(i);
if (res > highestres)
{
highestres = res;
}
}
Unfortunately I'm getting this error when I try to compile with GCC:
3np1.c:15: error: 'for' loop initial
declaration used outside C99 mode
I don't know what C99 mode is. Any ideas?
I'd try to declare i outside of the loop!
Good luck on solving 3n+1 :-)
Here's an example:
#include <stdio.h>
int main() {
int i;
/* for loop execution */
for (i = 10; i < 20; i++) {
printf("i: %d\n", i);
}
return 0;
}
Read more on for loops in C here.
There is a compiler switch which enables C99 mode, which amongst other things allows declaration of a variable inside the for loop. To turn it on use the compiler switch -std=c99
Or as #OysterD says, declare the variable outside the loop.
To switch to C99 mode in CodeBlocks, follow the next steps:
Click Project/Build options, then in tab Compiler Settings choose subtab Other options, and place -std=c99 in the text area, and click Ok.
This will turn C99 mode on for your Compiler.
I hope this will help someone!
I've gotten this error too.
for (int i=0;i<10;i++) { ..
is not valid in the C89/C90 standard. As OysterD says, you need to do:
int i;
for (i=0;i<10;i++) { ..
Your original code is allowed in C99 and later standards of the C language.
#Blorgbeard:
New Features in C99
inline functions
variable declaration no longer restricted to file scope or the start of a compound statement
several new data types, including long long int, optional extended integer types, an explicit boolean data type, and a complex type to represent complex numbers
variable-length arrays
support for one-line comments beginning with //, as in BCPL or C++
new library functions, such as snprintf
new header files, such as stdbool.h and inttypes.h
type-generic math functions (tgmath.h)
improved support for IEEE floating point
designated initializers
compound literals
support for variadic macros (macros of variable arity)
restrict qualification to allow more aggressive code optimization
http://en.wikipedia.org/wiki/C99
A Tour of C99
if you compile in C change
for (int i=0;i<10;i++) { ..
to
int i;
for (i=0;i<10;i++) { ..
You can also compile with the C99 switch set. Put -std=c99 in the compilation line:
gcc -std=c99 foo.c -o foo
REF: http://cplusplus.syntaxerrors.info/index.php?title='for'_loop_initial_declaration_used_outside_C99_mode
For anyone attempting to compile code from an external source that uses an automated build utility such as Make, to avoid having to track down the explicit gcc compilation calls you can set an environment variable. Enter on command prompt or put in .bashrc (or .bash_profile on Mac):
export CFLAGS="-std=c99"
Note that a similar solution applies if you run into a similar scenario with C++ compilation that requires C++ 11, you can use:
export CXXFLAGS="-std=c++11"
Jihene Stambouli answered OP question most directly...
Question was;
why does
for(int i = low; i <= high; ++i)
{
res = runalg(i);
if (res > highestres)
{
highestres = res;
}
}
produce the error;
3np1.c:15: error: 'for' loop initial declaration used outside C99 mode
for which the answer is
for(int i = low...
should be
int i;
for (i=low...
Enable C99 mode in Code::Blocks 16.01
Go to Settings-> Compiler...
In Compiler Flags section of Compiler settings tab, select checkbox 'Have gcc follow the 1999 ISO C language standard [-std=c99]'
I had the same problem and it works you just have to declare the i outside of the loop:
int i;
for(i = low; i <= high; ++i)
{
res = runalg(i);
if (res > highestres)
{
highestres = res;
}
}
For Qt-creator: just add next lines to *.pro file...
QMAKE_CFLAGS_DEBUG = \
-std=gnu99
QMAKE_CFLAGS_RELEASE = \
-std=gnu99

Resources