CMPLX Yields Undefined Symbol with GCC - c

I'm trying to hunt down a problem using complex literals when compiling with GCC. Consider the following
#include <stdio.h>
#include <complex.h>
int main(void)
{
double complex z = CMPLX(0.0, -1.0);
printf("z = %.1f%+.1fi\n", creal(z), cimag(z));
return 0;
}
(slightly modified from the reference page). If I compile with Clang, it works as expected. However, if I use GCC I get an undefined reference error
gcc -std=c11 mwe.c
mwe.c: 6:24 warning: implicit declaration of function 'CMPLX' ...
mwe.c:(...) undefined reference to `CMPLX'
I have tried this with GCC 4.7 and 7.2 on Linux and GCC 9 on MacOS. The error messages change, but the net result remains the same. Reviewing the reference for CMPLX, this should be valid C11. Based on this answer and this post, it appears like GCC accepted this construct before.
My bottom line question is: Why can't I use CMPLX with GCC?

It appears like this is caused by a header/library disconnect on the systems I have. Compiling with the -save-temps flag, it appears GCC uses the system header for complex.h. This means the selected Xcode SDK's usr/include/complex.h on MacOS and /usr/include/complex.h on Linux. On MacOS, the CMPLX macro is only defined when using Clang. The Linux I have is RHEL 6 meaning the header is aimed at GCC 3 which did not have CMPLX. Based on the discussion on this bug report, it looks like making sure the macro is defined is not up to GCC.
The short answer is: The compiler/platform combination doesn't support it. Use the native compiler or update the system.

Related

gcc linking with static libraries

I am reading a book titled "An Introduction to GCC" and would like some clarification. The book indicates that the code below will cause an error but when I compile, it builds and runs perfectly:
#include <math.h>
#include <stdio.h>
int main (void) {
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}
I quote from the book "Trying to create an executable from this source file alone causes the compiler to give an error at the link stage:"
$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function `main':
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference
to `sqrt'
The solution that the book gives is that you are supposed to include the path to the math library ‘libm.a’ as follows:
$ gcc -Wall calc.c /usr/lib/libm.a -o calc
It would be very inconvenient to have to specify the paths to built in libraries that we use in our programs. I can understand the reason for adding the path to my own custom libraries, but libm.a is built into gcc. And although the book is quite old (published in 2004), what has changed with more modern versions of gcc, so that we do not need to include the path to libm.a?
* UPDATE *
I noticed that the answer given by taskinoor demonstrates updated code that requires that I use the -lm flag if the value passed to sqrt() is not known at compile time.
I learned C/C++ using VS but my goal now is to learn and use gcc. I have Visual Studio 2013 and the VS compiler/linker does not seem so picky. For example, I am able to compile just about any simple program without having to specify mysterious compiler flags.
I am learning on gcc version 5.4 that comes with KUBUNTU 16.04.1
sqrt (2.0);
Modern GCC is well capable to determine that you are trying to find square root of a constant and thus it is able to calculate that in compile time. Your object code does not contain an actual call to sqrt.
If you use a variable which is input via scanf at run then it won't link without libm.
int main() {
double x;
scanf("%lf", &x);
printf("%lf\n", sqrt(x));
return 0;
}
Without libm gcc 4.8.4 on Ubuntu 14.04 this results:
/tmp/ccVO2fRY.o: In function `main':
sqrt.c:(.text+0x2c): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
But if I put a constant instead of x like your example then it links fine without libm.
P.S: I don't know the exact version since when GCC is able to do this. Hopefully someone else can point to that.
I've noticed that on some operating systems, common libraries are available without explicit linking. In particular, I've often taken a working C project originally developed on my Mac, and the project would not compile on Linux until I explicitly linked against the libraries I used (like libm).
Of course, this is typically for dynamic rather than static linking...

MinGW printf padding ignored with c89/c99/c11

Trying to build+run this simple C program in MinGW produces strange results
#include <stdio.h>
void main() {
printf("%03d", 7);
};
If I build it with any standard-C compliance flags (-std=c89/99/11) the padding is ignored:
C:\>gcc -std=c11 a.c
C:\>a
7
Whereas in regular GNU C mode it works fine:
C:\>gcc a.c
C:\>a
007
Is this a bug in MinGW? Have I missed something? Or is the padding specifier really not a standard C feature?
For reference, here's the output of gcc -v on my system.
As suggested by 2501, the best workaround is to instead use MinGW-W64, which is actually a separate project from MinGW. It can still produce 32-bit binaries, despite the "W64" label.

Compiling issue: undefined reference to pthread_cleanup_push_defer_np() and pthread_cleanup_pop_restore_np()

I am currently writing a C program with threads and I make use of pthread_cleanup_push_defer_np() and pthread_cleanup_pop_restore_np(). Provided that:
I have included pthread.h;
I am compiling with -pthread option;
I am on Ubuntu 14.04 and using gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1);
when compiling I get back a nasty undefined reference error to the above mentioned functions and I can't figure out why. I have tried to take a look into pthread.h and it seems those two functions are commented out, so I am wondering whether I need to enable them in some way or use some other kind of options. I've read the manual pages and google it up but I can't find a solution, so I would appreciate a little help. Here it is a snippet:
void *start_up(void *arg)
{
char *timestamp;
// ... code ...
timestamp = get_current_timestamp("humread");
pthread_cleanup_push_defer_np(free, timestamp);
// ... some other code
pthread_cleanup_pop_restore_np(1);
// ... more code ...
}
I compile with
gcc -pthread -o server *.c
The manual of pthread_cleanup_push_defer_np and pthread_cleanup_pop_restore_np say these two (non portable) functions are GNU extensions and are enabled
by defining _GNU_SOURCE:
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
pthread_cleanup_push_defer_np(), pthread_cleanup_pop_defer_np():
_GNU_SOURCE
This results in linker error (as opposed to compile time error) because your compiler is pre-C99 (or you are compiling in pre-C99 mode) and assumes these functions return int by default.
The rule functions-return-int if no prototype is present has been removed since C99. Enabling more compiler switches can help you with better diagnostics.

GCC error : undefined reference

I am trying to compile some C code on a beagleboard xm. I try to compile, but I get the error: undefined reference to 'isfinite' which is in the math.h library. This code compiles perfectly in all my other computers, and I do include -lm in my makefile.
I suspect that it may be my compiler, maybe it is an over version? On the beagleboard it's version 4.3.3, but on my computer it's 4.7.3, but I don't know how to get a later version. I thought opkg would automatically get the latest available.
Any ideas why this may be happening?
The function infinite() is part of C99. Your compiler is by default using an older version of the C language. You need to compile with the the flag -std=c99 to enable this macro.
`gnu89' GNU dialect of ISO C90 (including some C99 features). This is
the default for C code.
http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/C-Dialect-Options.html
isfinite is part of the C++11 standard and gcc 4.3.3 is to old to know that. Try
int finite(double x); or int finitef(float x);.

MinGW compiler doesn't need function declarations?

I have these two files:
// first.c
int main(void) {
putint(3);
}
and
// second.c
#include <stdio.h>
void putint(int n) {
printf("%d",n);
getchar();
}
When I run gcc 4.6.1 under Win XP:
gcc first.c second.c -o program.exe
It has no problem and writes 3 to stdout. It doesn't need putint declaration in first.c. How is this possible? Is this standard behavior?
I have tested this on MSVC 2008 Express and it runs only with the declaration as expected.
// first.c
void putint(int);
int main(void) {
putint(3);
}
Solved, thanks for hints, these options helped to show the warning:
-Wimplicit
-std=c99 (MinGW 4.6 still uses gnu90 by default)
This is a legacy "feature" of C that should not be used as of several decades ago. You should use a compiler with settings that will warn you if you do something like this. Gcc has several switches that you should specify when using it & one of them will give you a warning for this.
Edit: I haven't been using gcc myself, but switches that you should check out are -pedantic, -Wall, -Wextra, and -std.
The compiler that is accepting this is assuming, per the old language definition, that since you didn't see fit to tell it otherwise, the function a) returns an int value and b) since you pass it an int (or if you passed it something that could be promoted to an int) the function expects that argument to be an int.
As #veer correctly points out, this should generally work in your particular case. In other cases, however, differences between the implicit assumptions for a function without a prototype and the function's actual signature would make things go boom.
This isn't just for MinGW, but all standard versions of gcc. As noted, this is legal in C89; gcc defaults to 'gnu89' (not 99), which also accepts the code without warning. If you switch to c99 or gnu99 (or later, such as c11) you'll get a warning by default, but it will still compile.
As is noted by others, this is standard behavior for C conforming compilers. Naming your files .c partially puts it in C mode. It'll have fun things like "built-in functions" (printf() etc.) and all sorts of legacy C things.
I'd like to add to what others have said that I experienced recently, though. MS expressly dropped support for C past C90, and their C90 support is poor to say the least. I'm not entirely sure standard ANSI C90 codebases would compile under newer VS's, because it is basically the C++ compiler with lots of stuff disabled (whereas GCC actually has a C compiler). They did this in order to promote C++. If you want to use real C, you can't really do it in MS Visual Studio, any edition, unless you want to be declaring all your variables at the start of functions, etc.

Resources