I declared a variable in this way:
int i = 0;
I get the warning:
ISO C90 forbids mixed declarations and code
How can I fix it?
I think you should move the variable declaration to top of block. I.e.
{
foo();
int i = 0;
bar();
}
to
{
int i = 0;
foo();
bar();
}
Up until the C99 standard, all declarations had to come before any statements in a block:
void foo()
{
int i, j;
double k;
char *c;
// code
if (c)
{
int m, n;
// more code
}
// etc.
}
C99 allowed for mixing declarations and statements (like C++). Many compilers still default to C89, and some compilers (such as Microsoft's) don't support C99 at all.
So, you will need to do the following:
Determine if your compiler supports C99 or later; if it does, configure it so that it's compiling C99 instead of C89;
If your compiler doesn't support C99 or later, you will either need to find a different compiler that does support it, or rewrite your code so that all declarations come before any statements within the block.
Just use a compiler (or provide it with the arguments it needs) such that it compiles for a more recent version of the C standard, C99 or C11. E.g for the GCC family of compilers that would be -std=c99.
Make sure the variable is on the top part of the block, and in case you compile it with -ansi-pedantic, make sure it looks like this:
function() {
int i;
i = 0;
someCode();
}
To diagnose what really triggers the error, I would first try to remove = 0
If the error is tripped, then most likely the declaration goes after the code.
If no error, then it may be related to a C-standard enforcement/compile flags OR ...something else.
In any case, declare the variable in the beginning of the current scope. You may then initialize it separately. Indeed, if this variable deserves its own scope - delimit its definition in {}.
If the OP could clarify the context, then a more directed response would follow.
-Wdeclaration-after-statement minimal reproducible example
main.c
#!/usr/bin/env bash
set -eux
cat << EOF > main.c
#include <stdio.h>
int main(void) {
puts("hello");
int a = 1;
printf("%d\n", a);
return 0;
}
EOF
Give warning:
gcc -std=c89 -Wdeclaration-after-statement -Werror main.c
gcc -std=c99 -Wdeclaration-after-statement -Werror main.c
gcc -std=c89 -pedantic -Werror main.c
Don't give warning:
gcc -std=c89 -pedantic -Wno-declaration-after-statement -Werror main.c
gcc -std=c89 -Wno-declaration-after-statement -Werror main.c
gcc -std=c99 -pedantic -Werror main.c
gcc -std=c89 -Wall -Wextra -Werror main.c
# https://stackoverflow.com/questions/14737104/what-is-the-default-c-mode-for-the-current-gcc-especially-on-ubuntu/53063656#53063656
gcc -pedantic -Werror main.c
The warning:
main.c: In function ‘main’:
main.c:5:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int a = 1;
^~~
Tested on Ubuntu 16.04, GCC 6.4.0.
Ensure you made your declarations before any statements in the block.
For instance:
{
int i = 0;
printf("a string");/*the code is not a working code*/
}
I believe this should be helpful:
https://www.configrouter.com/iso-c90-forbids-mixed-declarations-and-code-in-c-30621/
Related
Short version
To prevent the compiler from raising a warning about unused variables I define the macro UNUSED as:
UNUSED(x)=x __attribute__((__unused__))
This macro is then employed in some functions' prototypes, for instance :
void ext(int foo, int UNUSED( bar ) )
However, doxygen is unhappy about that and returns some warnings:
/tmp/sandbox/main.cpp:13: warning: argument 'bar' of command #param is not found in the argument list of Dummy::ext(int foo, intUNUSEDbar)
/tmp/sandbox/main.cpp:13: warning: The following parameters of Dummy::ext(int foo, intUNUSEDbar) are not documented:
parameter 'UNUSED'
How should I tell doxygen to ignore the UNUSED macro ?
Long version
I have a code that looks like the following :
#include <iostream>
class Dummy
//! Dummy class
{
public :
//!Dummy function
/**
* \param foo First variable
* \param bar Second variable
*/
void ext(int foo, int UNUSED( bar ) )
{
std::cout << "foo = " << foo << std::endl;
}
};
//!Main function
int main(void)
{
Dummy MyDummy;
MyDummy.ext(1, 2);
return 0;
}
I compile it by invoking :
g++ -D 'UNUSED(x)=x __attribute__((__unused__))' main.cpp
To generate the default doxygen configuration file named Doxyfile I enter :
doxygen -g
Eventually, to generate the documentation I enter :
doxygen Doxyfile
The latter command outputs the following warning :
/tmp/sandbox/main.cpp:13: warning: argument 'bar' of command #param is not found in the argument list of Dummy::ext(int foo, intUNUSEDbar)
/tmp/sandbox/main.cpp:13: warning: The following parameters of Dummy::ext(int foo, intUNUSEDbar) are not documented:
parameter 'UNUSED'
Following instructions from the doxygen documentation, modify the Doxyfile so that it has the following parameters :
#Doxygen will run its own preprocessor before parsing the file
ENABLE_PREPROCESSING = YES
#The Doxygen preprocessor will not only define the macros (default
#behaviour) but also expand them
MACRO_EXPANSION = YES
#The Doxygen preprocessor will only expand the macros that are listed in
#the PREDEFINED setting. Any other macro will merely be defined, and not
#expanded.
EXPAND_ONLY_PREDEF = YES
#The Doxygen preprocessor will replace any occurrence of the UNUSED
#macro by its argument
PREDEFINED = UNUSED(x)=x
After those changes, invoking doxygen Doxyfile no longer raises warnings.
Working from:
Is ignoring __attribute__((packed)) always safe in SWIG interfaces?
Visual C++ equivalent of GCC's __attribute__ ((__packed__))
My .i does:
#define __attribute__(x)
then uses %include to include my cross-platform definition of PACK():
#if defined(SWIG)
#define PACK(...) VA_ARGS
#elif defined(_MSC_VER)
#define PACK(__Decl__) __pragma(pack(push, 1)) __Decl__ __pragma(pack(pop))
#else // GCC
#define PACK(__Decl__) __Decl__ __attribute__ ((packed))
#endif
Then I have code like:
PACK(
typedef struct {
uint8_t something;
uint32_t more;
} ) aName;
With earlier versions of the PACK() macro, I got syntax error from SWIG on the typedef line. Now I get past that but when compiling the SWIG-generated .c file, I have get and set functions that complain aName doesn't exist. The messages are like (edited):
libudr_perl_swig.c: In function '_wrap_aName_set':
libudr_perl_swig.c:2367:20: error: expected identifier or '(' before
'=' token libudr_perl_swig.c: In function '_wrap_aName_get':
libudr_perl_swig.c:2377:3: error: expected expression before 'aName'
SWIG sort of seems to know about my struct -- it creates access functions -- but the doesn't expose them enough that the access functions can find it.
Before I started to make this cross-platform -- when it was still Linux-only with __attribute__ ((packed)) -- it worked in SWIG. And it still works in Linux. So there appears to be something about SWIG's interpretation of PACK() that is flawed.
The old way generated a lot of per-field code like:
XS(_wrap_aName_something_set) {
{
aName *arg1 = (aName *) 0 ;
...
the new way generates a little per-struct code like:
SWIGCLASS_STATIC int _wrap_aName_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) {
MAGIC_PPERL
{
Why should my PACK() (which should be a no-op in SWIG) do that?
Googling "cpp standard variadic macros" leads to http://en.wikipedia.org/wiki/Variadic_macro which notes the expansion of ... is __VA_ARGS__, not VA_ARGS (as I had found somewhere). When I change my macro definition to be:
#if defined(SWIG)
#define PACK(...) __VA_ARGS__
#elif defined(_MSC_VER)
#define PACK(__Decl__) __pragma(pack(push, 1)) __Decl__ __pragma(pack(pop))
#else // GCC
#define PACK(__Decl__) __Decl__ __attribute__ ((packed))
#endif
it works.
in mongodb, class cursor is defined as 'Cursor : boost::noncopyable', and then there are many class which are derived from it. I want to know for a given operation from client, which XXXCursor was used. so I want to set a breakpoint on Cursor::Cursor. but failed.
(gdb) b mongo::Cursor::Cursor
the class mongo::Cursor does not have any method named Cursor
Hint: try 'mongo::Cursor::Cursor<TAB> or 'mongo::Cursor::Cursor<ESC-?>
(Note leading single quote.)
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) ptype mongo::Cursor
type = class mongo::Cursor : private boost::noncopyable_::noncopyable {
public:
~Cursor(int);
virtual bool ok(void);
bool eof(void);
virtual mongo::Record * _current(void);
virtual mongo::BSONObj current(void);
virtual mongo::DiskLoc currLoc(void);
virtual bool advance(void);
virtual mongo::BSONObj currKey(void) const;
....
}
(gdb) list mongo::Cursor::Cursor
**the class mongo::Cursor does not have any method named Cursor
Hint: try 'mongo::Cursor::Cursor<TAB> or 'mongo::Cursor::Cursor<ESC-?>**
(Note leading single quote.)
But I wrote a similar program
#include <iostream>
#include <boost/utility.hpp>
class Base : boost::noncopyable {
public:
void printx() {std::cout<< getx() <<"\n" ;}
virtual int getx()=0;
};
class P : public Base {
public:
int x;
virtual int getx() { return x*3;}
P(int c){ x= c;}
};
int main(){
P p(2);
p.printx();
return 0;
}
I can set breakpoint on Base::Base sucessfully.
do you have any idea why I can't set breakpoint on mongo::Cursor::Cursor ?
mongo::Cursor was definied here: https://github.com/mongodb/mongo/blob/master/src/mongo/db/cursor.h
As for your example. If I compile it like this:
g++ -O0 -g -m64 -I ./boost_1_53_0 main.cpp
I can set a breakpoint on Base::Base and I see Base::Base as a symbol:
>nm -C a.out | grep Base::Base
0000000000400a4e W Base::Base()
If I compile compile it like this (with optimization level O2):
g++ -O2 -g -m64 -I ./boost_1_53_0 main.cpp
I don't see Base::Base as a symbol:
>nm -C a.out | grep Base::Base
>
And can't set a breakpoint:
(gdb) b Base::Base
the class Base does not have any method named Base
Hint: try 'Base::Base<TAB> or 'Base::Base<ESC-?>
So as a first step make sure that there is mongo::Cursor::Cursor as a symbol in your program or shared library. It can be optimized out.
I'm using Eclipse and MinGW. I've got undefined reference to error to all that I write in h files, that I do include in cpp-file where main located. I create an empty project, and the same thing again (
main.cpp
#include <iostream>
#include "Stack.h"
using namespace std;
int main(){
Stack<int> stack(10);
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
stack.h
#ifndef STACK_H_
#define STACK_H_
template <class T>
class Stack{
private:
struct StackEl;
StackEl *top;
public:
Stack();
Stack(T el);
~Stack();
void Push(const T& el);
T Pop();
};
#endif /* STACK_H_ */
and stack.cpp inplements everything from stack.h
If I include not h-file, but cpp - all works. Help please!
I've got following errors
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:16: undefined reference to `Stack<int>::Stack(int)'
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:18: undefined reference to `Stack<int>::~Stack()'
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:18: undefined reference to `Stack<int>::~Stack()'
This is a linker error. I'm no Eclipse expert, but you have to tell it somehow to add Stack.o to the linking command.
If you include Stack.cpp instead of Stack.h, the implementations from the cpp-file get included into main.cpp by the preprocessor before compilation, so the linking stage has no unresolved references to outside functions.
My bad, that is becouse templates! When you use template, all code, including realization of functions, must be in header-file, or you have to write prototypes for every type you are going to use you template-functions with. I've forgot about that working with templates is not the same as with usual function :(
cat test.cpp
#include <iostream>
int main() {
int à;
}
results in:
clang++ test.cpp
test.cpp:4:7: error: expected unqualified-id
int à;
^
1 error generated.
Now, is there a way to get clang to allow unicode variable names?
Thanks!
While this is allowed by the standard, Clang does not currently support UCN (universal character name)s in identifiers.