I have the following two files:
file1.c
int main(){
foo();
return 0;
}
file2.c
void foo(){
}
Can I compile and link the two files together so the file1.c will recognize the foo function without adding extern?
Updated the prototype.
gcc file1.c file2.c throws: warning: implicit declaration of function foo.
The correct way is as follows:
file1.c
#include <stdio.h>
#include "file2.h"
int main(void){
printf("%s:%s:%d \n", __FILE__, __FUNCTION__, __LINE__);
foo();
return 0;
}
file2.h
void foo(void);
file2.c
#include <stdio.h>
#include "file2.h"
void foo(void) {
printf("%s:%s:%d \n", __FILE__, __func__, __LINE__);
return;
}
output
$
$ gcc file1.c file2.c -o file -Wall
$
$ ./file
file1.c:main:6
file2.c:foo:6
$
You don't need an extern, but file1.c must see a declaration that foo() exists. Usually this declaration is in a header file.
To add a forward declaration without using a header file, simply modify file1.c to:
int foo(); // add this declaration
int main(){
foo();
return 0;
}
You can, but you shouldn't.
Use a header file, file2.h:
// file2.h
void foo(); // prototype for function foo()
Then add:
#include "file2.h"
in file1.c
To compile:
$ gcc -Wall file1.c file2.c -o foo
As a general rule it's better (more robust) to use a header file to define the interface of each module rather than ad hoc prototypes within dependent modules. This is sometimes known as the SPOT (Single Point Of Truth) principle.
It's ugly, but using gcc, you could:
gcc -include file2.c file1.c
-include is a flag to the preprocessor which will include the contents of file2.c at the very top of file1.c. Having said that, it's a poor choice, and breaks down for all but the simplest of programs.
Related
I'm trying to understand Makefile. I understand the hole concept of the dependency tree, but why do we include .h files for the .o targets that include certain header file. Here is an example:
// main.c
#include <stdio.h>
#include "math.h"
int main() {
printf("%d\n", magic_number);
printf("%d\n", square(5));
}
// foo.h
const int magic_number = 10;
int square(int);
// foo.c
int square(int value) {
return value*value;
}
# -*- Makefile -*-
all: main
main: main.o foo.o
gcc main.o foo.o -o main
main.o: main.c #foo.h <-----------
gcc -c main.c
foo.o: foo.c
gcc -c foo.c
I commented the part out where I would add the header file. Because that's my question, why does it have to be there? I did some testing and added some more const int variables to the header. Just looking at the Makefile (with commented out foo.h) it would only recompile the main.c file. There it would then access a variable from the header. So why does it look into the header file even thought it's not in the Makefile?
Makefiles track dependencies - in this case it is an explicit dependency.
Specifying that main.o depends on both main.c and foo.h means that any time either file changes, main.o will be rebuilt.
If you didn't have that explicit dependency chain, then you could change foo.h in a way which renders main.c uncompilable, but Make wouldn't know about it so would not rebuild it when it should.
There are tons of ways that a header file can change in such a way that a source file doesn't need to also change, but yet the program is malformed if the source file is not rebuilt. Here's one simple example: say we have this source:
// foo.h
struct foo {
int f;
};
int getfoo(const struct foo* f);
// foo.c
#include "foo.h"
int getfoo(const struct foo* f)
{
return f->f;
}
// main.c
#include "foo.h"
int main()
{
struct foo f = {1};
return getfoo(&f);
}
You compile everything and all is well. Now suppose you modify foo.h like this:
// foo.h
struct foo {
const char* val; // added value
int f;
};
int getfoo(const struct foo* f);
And you modify main.c like this:
// main.c
#include "foo.h"
int main()
{
struct foo f = {"hello", 1};
return getfoo(&f);
}
Now you run make and since you've modified main.c it is recompiled, but since you haven't modified foo.c it is not recompiled.
Now your program will certainly return a bogus value since foo.o thinks that the structure it was passed contains just a single integer, but the structure it was really passed from main() actually has a pointer plus an integer.
I have been provided a library a that expects there to be a function b() but does not implement it. It looks like this (I can't change this code):
a.h:
void a();
a.c:
#include "a.h"
extern void b();
void a() {
b();
}
The library was compiled like this (assume all files in these examples are in the same directory for simplicity).:
gcc -shared a.c -o liba.so
I want to call a() in my code, so I write a program that looks like this:
main_v1.c:
#include "a.h"
int main(void) {
a();
return 0;
}
If I try to compile this, I'll get a linker error because b() hasn't been defined:
gcc main_v1.c -L ./ -la -o main
.//liba.so: undefined reference to `b'
collect2: error: ld returned 1 exit status
The simplest thing I can do is add a definition of b() right in my main.c:
main_v2.c:
#include <stdio.h>
#include "a.h"
void b() {
printf("b");
}
int main(void) {
a();
return 0;
}
gcc main_v2.c -L ./ -la -o main
This works. But what if I don't want to define b() in my main.c? For example, if I want to be able to re-use my b() implementation elsewhere? One think I know I can do is compile it into a second library and link against it, like this:
b_v1.c:
#include <stdio.h>
void b() {
printf("b");
}
gcc -shared b_v1.c -o libb.so
gcc main_v1.c -L ./ -la -lb -o main
This works too. Note that -lb must come after -la; it won't work the other way around.
But I'd really like to avoid compiling another library. Why can't I just do this?:
b.h:
void b();
b_v2.c:
#include <stdio.h>
#include "b.h"
void b() {
printf("b");
}
main_v3.c:
#include "a.h"
#include "b.h"
int main(void) {
a();
return 0;
}
gcc main_v3.c -L ./ -la -o main
This doesn't work. I get the same linker error:
.//liba.so: undefined reference to `b'
collect2: error: ld returned 1 exit status
Why not? How is this different from my first working example in main_v2.c? Is there a way to accomplish this without creating a separate library for b()?
As Mat pointed out, I was simply neglecting to include the b_v2.c source in the compilation step. This works:
gcc main_v3.c b_v2.c -L ./ -la -o main
How is this different from my first working example in main_v2.c?
In version 3, no implementation of b() is even compiled, much less linked into the final executable. A declaration alone is not sufficient, and including a header is completely independent of compiling or linking an associated source file.
Note that your a.c has exactly as much of a declaration of b() as main_v3.c acquires from b.h, so if nothing in main_v3.c calls that function, then that header is not adding anything new or useful.
Is there a way to accomplish this without creating a separate library for b()?
Sure, several. But the easiest one for you to use might be to just name both your C source files on the same compilation command line:
gcc main_v1.c b.c -L. -la -o main
Note that I have chosen main_v1 intentionally: since nothing in the file calls b(), it is not useful for a declaration of that function to appear in the file, whether directly or via header inclusion.
a.h
void a();
a.c
void b();
void a() {
b();
}
b.c
#include "a.h"
#include <unistd.h>
void b()
{
write(1, "test", 4);
}
compile
$> gcc *.c
exec
$> ./a.out
I have a test.c file which contains main() function and some test cases and it cannot be modified it(such as adding "include *.h"). Then I have a foo.c file which contains some functions(no main() function). These functions will be tested through test cases in test.c file. What I'm going to do is use foo.c as a library and link it to test.c file. And here is the simple code.
test.c
//cannot modify
int main(){
...
bar();
...
}
foo.c
#include "foo.h" //I will explain this below.
int bar(){
...
}
I'm trying to implement an interface using .h file, such as
foo.h
#ifndef _FOO_H_
#define _FOO_H_
extern int bar();
#endif
Then using cmd line
gcc -c foo.c
gcc -o output test.c foo.o
./output
You may guess the result. There is a warning that "implicit declaration of function 'bar' is invalid in C99 [-Wimplicit-function-declaration]". And the test.c file cannot run correctly.
Could someone help me about this? Thank you so much!
Your problem is:
test.c has a call to bar() in it.
test.c doesn't have any declaration for bar, nor does it have an #include for a .h file that declares bar.
You are not allowed to change test.c in any way to add either a declaration or an #include.
This is a hard problem. The C language requires there be a prototype/declaration for bar in test.c! It can be written directly in the test.c file (write extern int bar(); before you call it), or the declaration can come in from another file with an #include statement, but you must have it.
Luckily, GCC has a way to force an #include statement into a file while it's compiling the file. You don't have to change test.c in order to make it start with #include "foo.h". This will solve your problem:
gcc -c -include foo.h test.c
You need to include the declaration of bar in the test.c file:
#include "foo.h"
So that the compiler have the prototype in the translation unit, of test.c.
I'm wondering why is this code compiles and run. I thought that if a variable is declared as static (in global scope) it will be accessible only within the file it is declared.
functions.h
static int x = 10;
main.c
#include <stdio.h>
#include "functions.h"
extern int x;
int main()
{
printf("%d", x);
}
Technically, it is indeed declared within the main.c, as this includes the functions.h. If it was a sparate compilation module, you'd be right.
But I'd have suspected that within the same compilation unit extern and staticwould collide with each other. At least it would be worth a warning.
The preprocessor takes the text in functions.h and copies it as is into main.c
After preprocessing (and before compilation) your main.c looks as follows:
#include <stdio.h>
static int x = 10;
extern int x;
int main()
{
printf("%d", x);
}
You will have linker problems if functions.h is included into a second source file, and you try to link both object files into one executable.
when you are including functions.h in main.c , you are actually copy content of function.h in main.c so your final code become something like :
#include <stdio.h>
static int x = 10;
extern int x;
int main()
{
printf("%d", x);
}
So your extern line is redundant.
you can achieve what you want by this
remove #include "functions.h" from main.c
compile function.h using g++ -c function.h
compile main.c using g++ -c main.c
then build g++ function.o main.o -o out
third line would not compile because of static int .
I want to allow the redefinition of a function in a .c file that is already defined in a header file. According to GCC manual on the weakref attribute:
The effect is equivalent to moving all references to the alias to a separate translation unit, renaming the alias to the aliased symbol, declaring it as weak, compiling the two separate translation units and performing a reloadable link on them.
Which sounds like exactly what I want to do.
However, the following example does not compile with error:
tpp.c:18:13: error: redefinition of ‘foo’
tpp.c:6:13: note: previous definition of ‘foo’ was here
#include <sys/types.h>
#include <stdio.h>
/* this will be in a header file */
static void foo(void) __attribute__ ((weakref ("_foo")));
static void _foo(void)
{
printf("default foo\n");
}
/* in a .c file #including the header mentioned above */
#define CUSTOM_FOO
#ifdef CUSTOM_FOO
static void foo(void)
{
printf("user defined foo.\n");
}
#endif
int main(int argc, char **argv)
{
printf("calling foo.\n");
foo();
}
Am I using this correctly? What am I missing?
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
As far as I understand that you need to define that function as extern.
Then it work for me as follows:
user#horst:$ cat weakref.c
#include <sys/types.h>
#include <stdio.h>
/* this will be in a header file */
extern void foo(void) __attribute__ ((weak, alias ("_foo")));
void _foo(void)
{
printf("default foo\n");
}
int main(int argc, char **argv)
{
printf("calling foo.\n");
foo();
}
user#horst:$ gcc weakref.c
user#horst:$ ./a.out
calling foo.
default foo
user#horst:$ cat weakrefUser.c
#include <stdio.h>
/* in a .c file #including the header mentioned above */
#define CUSTOM_FOO
#ifdef CUSTOM_FOO
void foo(void)
{
printf("user defined foo.\n");
}
#endif
user#horst:$ gcc -c weakrefUser.c
user#horst:$ gcc -c weakref.c
user#horst:$ gcc weakref.o weakrefUser.o
user#horst:$ ./a.out
calling foo.
user defined foo.
Note1: It does not work with static functions, for the weak attribute, it need to be global.
Note2: Weak symbols are "only" supported for ELF targets.
Since I wanted to use weak or weakref, and the existing answer seemed incomplete, I decided to write up the options, and try to explain.
There are apparently three basic options:
Use weakref. In this case, you write a static definition of a different name referencing the name you want, and it may or may not be null. You need to test the function before calling it. In this case, the alias option must be included either explicitly or as a parameter on weakref.
Use weak without alias. In this case, things are simple and public. Again, it may or may not be null, and you must test it before calling it.
Use weak and alias. In this case, the call and the declared alias must (apparently) be in the same source file. In this case, there is always a definition for the symbol, so you don't need to test for it. If there is an external definition of the name, you will get that in leiu of the alias.
In C++, when providing an alias name, the name must be the mangled form. (This was relevant to me, not to OP.)
My test sources are:
cat weakref.c :
#include <stdio.h>
static void fooref(void) __attribute__((weakref("foo")));
int main(int argc, char **argv)
{
if (fooref) {
printf("calling foo.\n");
fooref();
} else {
printf("no foo to call. (do something default-ish)\n");
}
}
cat weak.c :
#include <stdio.h>
#include "header.h"
int main(int argc, char **argv)
{
if (foo) {
printf("calling foo.\n");
foo();
} else {
printf("no foo to call. (do something default-ish)\n");
}
}
cat weakalias.c :
#include <stdio.h>
#include "header.h"
extern void foo(void) __attribute__ ((weak, alias ("defaultfoo")));
void defaultfoo(void)
{
printf("default foo\n");
}
int main(int argc, char **argv)
{
printf("calling foo.\n");
foo();
}
cat header.h :
extern void foo(void) __attribute__ ((weak));
cat Makefile :
EXES = weakref weakreffoo weakalias weakaliasfoo weak weakfoo
all : ${EXES}
clean :
-rm ${EXES} *.o
weakref : weakref.o
gcc -o $# $^
weakreffoo : weakref.o foo.o
gcc -o $# $^
weakalias : weakalias.o header.h
gcc -o $# $^
weakaliasfoo : weakalias.o foo.o header.h
gcc -o $# $^
weak : weak.o header.h
gcc -o $# $^
weakfoo : weak.o foo.o header.h
gcc -o $# $^
cat foo.c :
#include <sys/types.h>
#include <stdio.h>
void foo(void)
{
printf("custom foo\n");
}
My output reads:
$ ./weakref
no foo to call. (do something default-ish)
$ ./weakreffoo
calling foo.
custom foo
$ ./weak
no foo to call. (do something default-ish)
$ ./weakfoo
calling foo.
custom foo
$ ./weakalias
calling foo.
default foo
$ ./weakaliasfoo
calling foo.
custom foo
$
I initially decided on weakref, but am now leaning towards weak.