No compile error without multiple inclusion guard - gcc

Not including the #ifndef guard to prevent multiple header file inclusions, does not throw compile error. Why is that?
// main.c
#include <stdio.h>
#include "declare.h"
#include "declare.h" //Shouldn't I get compiler error here
int main(){
printf("Hello World\n");
}
// declare.h
#define a 1 //just this define in declare.h file
Command used to compile: gcc main.c -std=c89

Including a header multiple times is not an error, either with or without guards.
Guards prevent you from redefining objects and functions, when you do so.
But you haven't done that. You've just redefined a macro with the same value it had before. Which is fine.
You can test this by just compiling the following file:
#define a 1
#define a 1
It's fine.
[C89: 6.8.3]: [..] An identifier currently defined as a macro without use of lparen (an object-like macro) may be redefined by another #define preprocessing directive provided that the second definition is an object-like macro definition and the two replacement lists are identical. [..]
Start putting more complex stuff in that header and you'll see a problem.

Related

What is the difference between crypt in unistd.h and crypt.h?

Background
crypt has two definitions, from the docs,
One of them uses unistd.h
#define _XOPEN_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
This is defined as
#ifdef __USE_MISC
extern char *crypt (const char *__key, const char *__salt)
__THROW __nonnull ((1, 2));
#endif
One of them uses GNU crypt.h
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <crypt.h>
This is defined as
extern char *crypt (const char *__phrase, const char *__salt)
__THROW __nonnull ((1, 2));
Problem
When I compile with the definition in the first example (unistd.h)
#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
int main()
{
printf("%s", crypt("foobar", "sa"));
}
I'm getting the error
In function ‘main’:
warning: implicit declaration of function ‘crypt’; did you mean ‘chroot’? [-Wimplicit-function-declaration]
printf("%s", crypt("foobar", "sa"));
^~~~~
chroot
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s", crypt("foobar", "sa"));
~^ ~~~~~~~~~~~~~~~~~~~~~
%d
Out of desperation, I've tried adding this.
#define _XOPEN_VERSION 700
#define _POSIX_VERSION 200809L
#define __USE_MISC 1
On Ubuntu Trusty 14.04 I believe this works fine use the unistd.h declaration, which makes all the more confusing.
These are two declarations, not two definitions. The content of the header file has no impact on which definition of a function is included: this is determined by the linker. There is only one definition of the crypt function in the Unix C standard library, it's whatever the symbol crypt points to in libcrypt.a or libcrypt.so (depending on whether you link statically or dynamically).
Since the two declarations are compatible, it doesn't matter which header a program gets its through. It's also fine if both declarations are processed: a program can contain any number of declarations for a function as long as they're compatible. Without going into the exact details (refer to the C language specification), two function declarations are compatible if they have the same return type, the same number of arguments and the same type for each argument. The name of the argument given in a declaration is not significant.
You should ignore unistd.h. That declaration is there for POSIX compatibility but GLIB has removed the definition for crypt when they migrated to libxcrypt to develop those features in isolation of glibc. This means you can still get ABI-compatibility but must link in the crypt. You can read more about that here
Availability in glibc
The crypt (), encrypt (), and setkey () functions are part of the POSIX.1-2008 XSI Options Group for Encryption and are optional. If the interfaces are not available then the symbolic constant _XOPEN_CRYPT is either not defined or defined to -1, and can be checked at runtime with sysconf ().
This may be the case if the downstream distribution has switched from glibc crypt to libxcrypt. When recompiling applications in such distributions the
user must detect if _XOPEN_CRPYT is not available and include crypt.h for the function prototypes; otherwise libxcrypt is a ABI compatible drop-in replacement.
As for why even if you link the definition isn't pulled down with
#define _XOPEN_VERSION 700
#define _POSIX_VERSION 200809L
#define __USE_MISC 1
#define _XOPEN_SOURCE
Well there are a few things that happening there
The only header that matters in unistd.h is __USE_MISC.
unistd.h includes features.h which undefs the __USE_ macros to start with a "clean slate"
The only way to define __USE_MISC is to have defined _GNU_SOURCE.
If you want to pull in the declaration of crypt.h from unistd.h you must define _GNU_SOURCE! Those two examples cited from man page of crypt.h do the same thing and whether you include unistd.h or crypt.h you MUST also define _GNU_SOURCE in contemporary versions of glibc.
So you can either do,
#define _GNU_SOURCE
#include <unistd.h>
Or,
#define _GNU_SOURCE
#include <crypt.h>
But because you must link against crypt (-lcrypt) I would suggest using the declaration in crypt.h for sanity.

does g++ with extern "C" really gives the same environment as gcc does?

I am writing a code using other packages in C languages and some in C++ langauges. So my code, needs to work with C routines, and C++ classes as well. My plan is, to include all the header files in C with extern "C" {} method and use g++ to compile.
So, I copied all the headers in C to a directory and added headers and footers like,
#ifdef __cplusplus
extern "C" {
#endif
//...
#ifdef __cplusplus
}
#endif
However, it still doesn't compile. So I made a mock C program to make it look clear how the problem shows up.
main.C
#include <stdio.h>
#include <A.h> //This is the problematic header file.
int main()
{
struct MMM m; //some struct in A.h
printf("How many times do I have to compile this? %d\n",1000);
return 0;
}
A.h
#ifndef _A_H
#define _A_H
#ifndef ...
#define ... ...
#endif
#include <B.h>
#include <C.h>
#endif
And it gives me the same error messages while compiling the mock program as the ones during compilation of the real code I was working on. And it is about some preprocessor macro functions defined in B.h and C.h. But I want to assure you all these header files are written inside extern "C" {}. Mock program is written in C language only so I was able to check there is no error messages with gcc and it works great.
So what I am wondering is, doesn't the g++ with extern "C" work just as gcc? Or did I miss something? Is there any suggestions to go around this problem?
extern "C" does not turn a C++ compiler into a C compiler. The code still has to be valid C++ code. It cannot use new keywords as identifiers, there is no implicit cast from void * to other pointer types, and so on. extern "C" only affects linkage (basically, how the code interacts with other translation units). It does not change the source language the compiler accepts.

cpp: delay #include's until second pass

I'm running my source file through the C preprocessor twice before compiling it, and I want to delay The #include directives until the second pass.
Intuitively, I tried this, but it doesn't work:
##include <zlib.h>
I just need a construct, that when preprocessed, will give #include mylib.
You could define a macro, like
#define INCLUDE #include
and then when you include stuff, use the macro instead.
INCLUDE <zlib.h>
In GCC's preprocessor, at least, that gives me #include <zlib.h>.

How do you suppress GCC linker warnings?

I've been on a crusade lately to eliminate warnings from our code and have become more familiar with GCC warning flags (such as -Wall, -Wno-<warning to disable>, -fdiagnostics-show-option, etc.). However I haven't been able to figure out how to disable (or even control) linker warnings. The most common linker warning that I was getting is of the following form:
ld: warning: <some symbol> has different visibility (default) in
<path/to/library.a> and (hidden) in <path/to/my/class.o>
The reason I was getting this was because the library I was using was built using the default visibility while my application is built with hidden visibility. I've fixed this by rebuilding the library with hidden visibility.
My question though is: how would I suppress that warning if I wanted to? It's not something that I need to do now that I've figured out how to fix it but I'm still curious as to how you'd suppress that particular warning — or any linker warnings in general?
Using the -fdiagnostics-show-option for any of the C/C++/linker flags doesn't say where that warning comes from like with other compiler warnings.
Actually, you can't disable a GCC linker warning, as it's stored in a specific section of the binary library you're linking with. (The section is called .gnu.warning.symbol)
You can however mute it, like this (this is extracted from libc-symbols.h):
Without it:
#include <sys/stat.h>
int main()
{
lchmod("/path/to/whatever", 0666);
return 0;
}
Gives:
$ gcc a.c
/tmp/cc0TGjC8.o: in function « main »:
a.c:(.text+0xf): WARNING: lchmod is not implemented and will always fail
With disabling:
#include <sys/stat.h>
/* We want the .gnu.warning.SYMBOL section to be unallocated. */
#define __make_section_unallocated(section_string) \
__asm__ (".section " section_string "\n\t.previous");
/* When a reference to SYMBOL is encountered, the linker will emit a
warning message MSG. */
#define silent_warning(symbol) \
__make_section_unallocated (".gnu.warning." #symbol)
silent_warning(lchmod)
int main()
{
lchmod("/path/to/whatever", 0666);
return 0;
}
gives:
$ gcc a.c
/tmp/cc195eKj.o: in function « main »:
a.c:(.text+0xf): WARNING:
With hiding:
#include <sys/stat.h>
#define __hide_section_warning(section_string) \
__asm__ (".section " section_string "\n.string \"\rHello world! \"\n\t.previous");
/* If you want to hide the linker's output */
#define hide_warning(symbol) \
__hide_section_warning (".gnu.warning." #symbol)
hide_warning(lchmod)
int main()
{
lchmod("/path/to/whatever", 0666);
return 0;
}
gives:
$ gcc a.c
/tmp/cc195eKj.o: in function « main »:
Hello world!
Obviously, in that case, replace Hello world! either by multiple space or some advertisement for your wonderful project.
Unfortunately ld does not appear to have any intrinsic way of suppressing specific options. One thing that I found useful was limiting the number of duplicate warnings by passing -Wl,--warn-once to g++ (or you can pass --warn-once directly to ld).

How to undefine a define at commandline using gcc

How do I at compile time undefine a compiler macro using gcc. I tried some compile args to gcc like -D but I can't get to see the "not defined" message.
Thanks
#include <iostream>
#define MYDEF
int main(){
#ifdef MYDEF
std::cout<<"defined\n";
#else
std::cout<<"not defined\n";
#endif
}
You can use the -U option with gcc, but it won't undefine a macro defined in your source code. As far as I know, there's no way to do that.
You should wrap the MYDEF definition in a preprocessor macro, the presence of which (defined on the command line) would then prevent MYDEF from being defined. A bit convoluted to be sure but you can then control the build in the way you want from the command line (or Makefile). Example:
#ifndef DONT_DEFINE_MYDEF
#define MYDEF
#endif
Then from the command line when you don't want MYDEF:
gcc -DDONT_DEFINE_MYDEF ...
http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Preprocessor-Options.html#Preprocessor-Options
The -U options seemed like what you could have needed... but then again you can't override a definition contained in your source code without resorting to more preprocessor directives.
You can resort to filtering source code and give this back to gcc for compilation, like this pseudo code:
grep -v "define MYDEF" yourFile.c | gcc -o yourFile.o -xc -
Hope it helps.
The code use case is not right. As I see, you have hard coded #define in the file. If compiler initially assumes MYDEF undefined, it will define it once it start processing the file.
You should remove the line #define MYDEF. And I hope your test case will work, if you pass MYDEF to -D and -U.
Here is one possibility that doesn't completely cover your use case but which I found to be helpful in my case.
If your MYDEF were #defined in a separate header file #included from the .c file you could force the definition of the #include guard macro with the -D option (thus preventing the MYDEF #definition) then either actively #define (still with the -D option) MYDEF to something else or just leave it undefined.
It is clear that anything else defined in the header file would also be missing but this was for me a solution to forcedly undefine a macro without changing the third-party code.

Resources