I wrote a program in C with Ubuntu Linux and now I need to port it over to a UNIX machine (or what I believe to be a UNIX box). It compiles fine on my Ubuntu with GCC but when I try to compile it with GCC on the UNIX box, it gives this error:
a.c: In function `goUpDir':
a.c:44: parse error before `char'
a.c:45: `newDir' undeclared (first use in this function)
a.c:45: (Each undeclared identifier is reported only once
a.c:45: for each function it appears in.)
a.c: In function `goIntoDir':
a.c:54: parse error before `char'
a.c:57: `newDir' undeclared (first use in this function)
a.c:57: `oldDir' undeclared (first use in this function)
The main problems seem to be the parse error before char (the others are related)
44 char newDir[50] = "";
54 char* oldDir = (char*)get_current_dir_name();
These are just simple C-style strings declarations. Is there a header file that I need to include to get it to work in UNIX?
P.S. what is the command to see what version of unix and which version of gcc you are using? Knowing this will allow me to be more specific in my question.
Thanks
If you are compiling pure C, variables must be declared on the beggining of the functions. I mention this because most people compile their C programs using C++ compilers, which offers then some resources not normally available to pure C compilers, the most common example being the // comment lines.
If you want to make sure your code is portable always use the -pedantic or -pedantic-errors.
This will provide warnings/errors where your code strays from standards compliance.
While we are on the subject. You should probably also turn on all the warnings. There are good reasons why the compiler warns you; when moving code from one platform to another these warnings are the source of potential bugs as the new hardware/OS/Compiler may not act the same as your current one.
Also use the correct GCC frontend executable: g++ Will treat *.c files like C++ files unless you explicitly tell it not too. So if you are compiling real C then use gcc not g++.
gcc -pedantic -Wall -Werror *.c
g++ -pedantic -Wall -Werror *.cpp
To help with your specific problem it may be nice to see line 43. Though the error says line 44 a lot of problems are caused by the proceeding line having a problem and the problem not being detected by the parser until you get to the first lexeme on the next line.
How did you copy the file over? Is it possible that you inserted something that shouldn't be there?
BTW: Please fix up your use of the code tag in your code - it's currently nearly impossible to read without using "view source" in my browser.
As for you end questions:
uname -a
gcc -v
When trying to write portable code, the following compiler flags will tell you about a lot of problems before you get as far as trying to compile the code on the next platform:
-std=c89 -pedantic -Wall
If you only need to target GCC on other platforms, not any other compilers, then you could try:
-std=gnu89 -pedantic -Wall
But I'd guess this might allow GNU extensions on a newer GCC that aren't supported on an older one. I'm not sure.
Note that although it would be nice if -pedantic was guaranteed to warn about all non-standard programs, it isn't. There are still some things it misses.
You will have to provide us with more context for the errors...at least one, probably several lines before lines 44 and 54. At a guess, if you give us the code from the start of the function definition before line 44 (perhaps line 40 or so) through to line 54 (or a few lines later - maybe line 60 - then we may be able to help. Something is up with the information before line 44 that is causing it to expect something other than 'char' at line 44; ditto (probably the same problem) at line 54.
The information is insufficient. The code above is at least as intersting and one has to
know if ones talks about ANSI C89 or ANSI C99. The first answer is wrong in that broad sense.
Regards
Friedrich
Steve,
The first error message says "parse error before 'char'". What is the code that precedes char? Is it a function declaration? Does it include any user-defined types or anything of the sort?
The most likely source of this error is that something shortly above line 44 uses a type or macro that's declared in a header file... that header file may differ between your own Ubuntu system and the one you're trying to compile on.
What UNIX is it? AIX, Ultrix, Minix, Xenix?
GCC has a "--version" flag:
gcc --version
To display the GCC version:
gcc --version
It might help to show the function so we could see the surrounding code. That is often the problem with "parse error before" type errors.
Related
The carefully crafted, self-including code in this IOCCC winning entry from 1988:
http://www.ioccc.org/years.html#1988_isaak
...was still too much for certain systems back then. Also, ANSI C was finally emerging as a stable alternative to the chaotic K&R ecosystem. As a result, the IOCCC judges also provided an ANSI version of this entry:
http://www.ioccc.org/1988/isaak.ansi.c
Its main attraction is its gimmick of including <stdio.h> in the last line (!) with well-thought-out #defines, both inside the source and at compile time, to only allow certain parts of the code into the right level. This is what allows the <stdio.h> header to be ultimately included at the latest stage possible, just before it is necessary, in the source fed to the compiler.
However, this version still fails to produce its output when compiled today, with the provided compiler settings:
gcc -std=c89 -DI=B -DO=- -Dy isaak.ansi.c
tcc -DI=B -DO=- -Dy isaak.ansi.c
Versions used: GCC 9.3.0, TCC 0.9.27
There isn't any evident reliance on the compiled binary filename, hence I left it to the compiler's choice. Even when using -o isaak or -o isaak.ansi, the same result happens: no output.
What is causing this? How are the output functions failing? What can be done to correct this?
Thanks in advance!
NOTE: The IOCCC judges, realising that this entry had portability issues that would detract from its obfuscation value, decided to also include a UUENCODEd version of the code's output:
http://www.ioccc.org/1988/isaak.encode
There is nothing remotely portable about this program. As I see it tries to overwrite the exit standard library function with its own code, expecting that return from empty main() would call that exit(), which is not true. And even then, such behaviour is not standard-conforming - even C89 said it would have undefined behaviour.
You can "fix" the program on modern GCC / Linux by actually calling exit(); inside main - just change the first line to
main(){exit(0);}
I compiled gcc -std=c89 -DI=B -DO=- -Dy isaak.ansi.c and run ./a.out and got sensible output out.
Code as below:
int main (int argc, char *argv[]) {
long pid = (long)getpid();
long test = pid + 1;
}
Have not included any head files, still can compile code successfully and still can run program successfully.
Why?
Environment info: Ubuntu 18.04.2 LTS, gcc (Ubuntu 4.8.5-4ubuntu8) 4.8.5
Have not included any head files,still can compile code successfully.
still can run program successfuly.Why?
Why not?
All question of whether the particular code presented conforms to the language standard notwithstanding, language non-conformance does not imply that compilation or execution must fail. Instead, you get undefined behavior, which can manifest in any manner within the power of the machine to produce, including compiling successfully and running as intended.
In your particular case, however, you are using GCC 4.8.5. The GCC 4.8 series defaults to compiling for the C90 standard, with GNU extensions. C90 allows calls to functions with no in-scope declaration, for compatibility with earlier, pre-standardization practice. That is no longer allowed in C99 or later, but many implementations nevertheless continue to accept it as an extension.
It should be understood, however, that C interprets some argument lists differently when the called function has an in-scope prototype than when it doesn't (which may be the case even for functions that are declared, because not all declarations provide prototypes). You may be able to get away with calling undeclared functions under some circumstances, but it is poor style, and if you do it enough then it will bite you at some point.
Note also that GCC 4 definitely has the ability to emit warnings about usage such as yours, even when compiling in C90 or GNU90 mode. You would be well served to turn on the -Wall option when you compile, and maybe additional warning options as well.
Normally, to use a dynamic library function you would have to link against the specified library at compile time through the -l switch, like for example gcc -lm prog.c when using the mathematic functions (from libm).
However, since it's so common, GCC always links the standard C library by default, meaning that doing gcc prog.c is actually the same as doing gcc -lc prog.c. This is always done whether you include any header or not.
The second thing that makes this work, is that GCC assumes any function that has not been declared at compile time to have the signature int func(void). In this case, the signature is quite similar to the one of the real getpid() function.
If you take a look at your compiled program with the ldd tool to show which dynamic libraries are required, you'll see that the program is linked against libc:
$ ldd prog
linux-vdso.so.1 (0x00007ffede7d0000)
==> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0f47018000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0f475b9000)
When your program runs, it asks the dynamic loader where (at which address) to find the getpid function before calling it the first time. The dynamic loaders checks the loaded libraries, and finds a function with that name in libc, so everything seems to work without a problem.
You can tell GCC to not link against the standard library by default using the -nostdlib compiler switch, but this is not that useful in your case. The real solution is to always treat warnings about implicit function declarations as errors (-Werror=implicit-function-declaration).
If your compiler doesn't give this warning by default, I would suggest you to upgrade it to a newer version. GCC 4 is definitely not the latest version available for Ubuntu 18.
$ sudo apt update
$ sudo apt upgrade
I want to get rid of all implicit-function-declaration warnings in my codebase. But there is a problem because some functions are
programmed into the microcontroller ROM at the factory and during linking a linker script provides only the function address. These functions are called by code in the SDK.
During compilation gcc of course emits the warning implicit-function-declaration. How can I get rid of this warning?
To be clear I understand why the warning is there and what does it mean. But in this particular case the developers of SDK guarantee that the code will work with implicit rules (i.e. implicit function takes only ints and returns an int). So this warning is a false positive.
This is gnu-C-99 only, no c++.
Ideas:
Guess the argument types, write a prototype in a header and include that?
Tell gcc to treat such functions as false positive with some gcc attribute?
You can either create a prototype function in a header, or suppress the warnings with the following:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
/* line where GCC complains about implicit function declaration */
#pragma GCC diagnostic pop
Write a small program that generates a header file romfunctions.h from the linker script, with a line like this
int rom_function();
for each symbol defined by the ROM. Run this program from your Makefiles. Change all of the files that use these functions to include romfunctions.h. This way, if the linker script changes, you don't have to update the header file by hand.
Because most of my programming expertise was acquired by self-study, I intentionally have become somewhat anal about resolving non-fatal warnings, specifically to avoid picking up bad coding habits. But, this has revealed to me that such bad coding habits are quite common, even from formally trained programmers. In particular, for someone like me who is also anal about NOT using MS Windows, my self-study of so-called platform-independent code such as OpenGL and Vulkan has revealed a WORLD of bad coding habits, particularly as I examine code written assuming the student was using Visual Studio and a Windows C/C++ compiler.
Recently, I encountered NUMEROUS non-fatal warnings as I designed an Ubuntu Qt Console implementation of an online example of how to use SPIR-V shaders with OpenGL. I finally threw in the towel and added the following lines to my qmake .PRO file to get rid of the non-fatal-warnings (after, first, studying each one and convincing myself it could be safely ignored) :
QMAKE_CFLAGS += -Wno-implicit-function-declaration
-Wno-address-of-packed-member
[Completely written due to commends]
You are compiling the vendor SDK with your own code. This is not typically what you want to do.
What you do is you build their SDK files with gcc -c -Wno-implicit-function-declaration and and your own files with gcc -c or possibly gcc -o output all-your-c-files all-their-o-files.
C does not require that declarations be prototypes, so you can get rid of the problem (which should be a hard error, not a warning, since implicit declarations are not valid C) by using a non-prototype declaration, which requires only knowing the return type. For example:
int foo();
Since "implicit declarations" were historically treated as returning int, you can simply use int for all of them.
If you are using C program, use
#include <stdio.h>
I saw yet another question about C where the code was using gets(),
and I commented with the usual warning about never using gets() except
when you want to demonstrate how to break security.
This time, I decided to check if my compiler issued a warning about the
use of gets(). Of course I expected it would. Has to, right? Even if
you don’t specify any warnings?
Imagine my surprise when I found that, not only does the compiler not
warn by default, but I couldn’t even figure out how to make it warn!
The compiler in question is gcc 4.7.2 on Debian, and here’s the code I
used:
#include <stdio.h>
int main(void)
{
char s[10];
gets(s);
puts(s);
return 0;
}
Tried gcc g.c. Compiles with no warnings. Runs. Gets a segfault if
you enter too much text.
Tried with all the standard warnings I normally put in a makefile:
gcc -W -Wall -Wno-long-long -Wshadow -Wlarger-than-1000 \
-Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align \
-Wconversion -Waggregate-return -Wmissing-prototypes \
-Wmissing-declarations -Wpadded -Wredundant-decls -Wnested-externs g.c
Same result.
Tried with -std=c11. Even that didn’t generate a warning, which is
pretty weird, considering gets() doesn’t even exist in C11. Tried
c99 too. No warning.
So what’s going on here? Why doesn’t this very widely used compiler warn
me when I use the most deprecated function in the entire C language?
EDIT: Acting on Keith Thompson’s suggestion below, I checked for a
deprecation attribute in stdio.h. It was not there. I then copied the
header file and experimented. Adding either of these strings (which I
found in other headers) to the end of the declaration did generate a
warning:
__attribute_deprecated__
__attribute__ ((__deprecated__))
The warning:
‘gets’ is deprecated (declared at /usr/include/stdiotz.h:632) [-Wdeprecated-declarations]
To summarize the responses I’ve seen so far, it appears that the version
of libc on my system doesn’t include the warning, which does exist in
later versions. This is strange, since the warning has existed in some
form since at least 1996. I vaguely recall that libc has been forked at
least once, so perhaps the warning was left out of one branch
significantly later than in other branches.
I think I will ask on the Debian mailing lists about this, and perhaps
report it as a bug, depending on what I learn.
EDIT 2: I’ve looked at some source code. glibc has had the warning
since 2007 at least, in libio/iogets.c. eglibc 2.13, the one I have,
has exactly the same warning code:
#ifdef _LIBC
link_warning (gets, "the `gets' function is dangerous and should not be used.")
#endif
I suppose _LIBC wasn’t defined when the library was compiled. Why, I
don’t know. I’m not sure what the purpose of _LIBC is.
So, the answer seems to come down to “It’s the library, and for whatever
reason, in their wisdom, the Debian developer responsible for it
compiled it that way.” We may never know why.
Not going to report it as a bug, since I’m using oldstable. Might bring
it up if it’s still that way after my next upgrade.
Thanks, everyone, for your informative responses!
It's not the GCC that includes this warning message, it's the GLIBC.
It's unlikely that you're using too old version of GLIBC: the warning has been around at least since 1996. See the line 67 of this GLIBC code on GitHub for an example (note the date: 15 Dec 1996):
link_warning (gets, "the `gets' function is dangerous and should not be used.")
Most likely you're using a different C library.
I have a C file heapsort.c which Im trying to compile on a 64 bit linux machine to output the corresponding assembly code. Im using the following command:
gcc -02 -S heapsort.c
when I type this Im getting this error message
gcc:error: unrecognized option '-02'
I tried googling this error but nothing helpful came up. Any suggestions on how to navigate this error and get the x86 output?
The flag is -O2, not -02. That's a letter O for "optimization", not a number 0. You might want to look into using a font that makes the difference more obvious.
I suggest even (as every pointed out is is the letter O not the digit 0)
gcc -O2 -fverbose-asm -S heapsort.c
The -fverbose-asm will give you more generated comments in the assembly file heapsort.s
BTW, passing -Wall to GCC is always a good habit.
if you are really curious and want to understand a bit more the internal representations inside GCC try even
gcc -fdump-tree-all -O2 -S heapsort.c
but be prepared to get a lot of files.
You'll get hundreds of them, matching heapsort.c.*!
If you want some crude GUI interface to query the Gimple internal representation at some arbitrary source code position, consider using MELT. MELT is mostly a high-level domain specific language (with a Lisp-like syntax, powerful pattern matching, object oriented, functional, dynamically typed, ....) to extend GCC, but you can also use its (crude) probe to query interactively some of the GCC internal representations.
It should be -O2 with 'O' not "zero"
Try -O2 instead of -02. It's a letter 'O' and shorthand for "optimization level 2".