My a.c file:
int sum(int a, int b) {
return a + b;
}
My b.c file:
#include<stdio.h>
extern int sum(int, int);
int main() {
printf ("%d", sum(2, 3));
return 0;
}
gcc a.c b.c -o output, working fine.
Let say tomorrow, I change the definition of "a.c file" sum function by increasing the argument to three. Like this,
int sum(int a, int b, int c) {
return a + b + c;
}
But forget to change the usage in b.c file (means I'm still using with two variable)
gcc a.c b.c -o output (doesn't give compilation error or warning mssg, printf gives wrong answer, obviously)
Now consider I'm working in huge set of c file and I cannot make new header file, because it will create unnecessary dependency problem which may take huge time to resolve.
What is the best way to throw error or even warning message in case the extern original definition is changed in terms of argument ?
Regards
What is the best way to throw error or even warning message in case the extern original definition is changed in terms of argument?
Neither compiler nor linker will object to that. You'll just find out at runtime (if you are lucky) when your program stops working.
If this was C++ then name mangling would allow the linker to reject such mal-formed programs. However, for C the linker only needs to find a symbol with the right name. It has no means of checking the signature.
Using header files is the accepted way to get the compiler to make sure you do things right. Repeating function declarations over and over throughout your program is usually a very bad idea. Whatever downsides you perceive to using header files pale into insignificance when compared to your proposed approach.
If you simply won't use header files, then you'll just have to always be right!
Normally editors like (SourceInsight,Sublime) have the options to browse the symbols. By using this option you can easily find function calls and prototype.
Compiler never generate warnings or error for your problem.Self contained header files are best option to avoid this situation.
The best thing to do is try to avoid "extern" and include the header file for sum(). Using header files and prototyping your functions will help the compiler catch these issues.
test.c:
#include <stdio.h>
#include "math.h"
int main(void)
{
printf("%d", sum(2, 3));
return 0;
}
math.h:
int sum(int a, int b, int c)
{
return (a + b + c);
}
output:
~]$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6:5: error: too few arguments to function ‘sum’
printf("%d", sum(2, 3));
^
In file included from test.c:2:0:
math.h:1:5: note: declared here
int sum(int a, int b, int c)
Related
Just a simple program, but I keep getting this compiler error. I'm using MinGW for the compiler.
Here's the header file, point.h:
//type for a Cartesian point
typedef struct {
double x;
double y;
} Point;
Point create(double x, double y);
Point midpoint(Point p, Point q);
And here's point.c:
//This is the implementation of the point type
#include "point.h"
int main() {
return 0;
}
Point create(double x, double y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Point midpoint(Point p, Point q) {
Point mid;
mid.x = (p.x + q.x) / 2;
mid.y = (p.y + q.y) / 2;
return mid;
}
And here's where the compiler issue comes in. I keep getting:
testpoint.c: undefined reference to 'create(double x, double y)'
While it is defined in point.c.
This is a separate file called testpoint.c:
#include "point.h"
#include <assert.h>
#include <stdio.h>
int main() {
double x = 1;
double y = 1;
Point p = create(x, y);
assert(p.x == 1);
return 0;
}
I'm at a loss as to what the issue could be.
How are you doing the compiling and linking? You'll need to specify both files, something like:
gcc testpoint.c point.c
...so that it knows to link the functions from both together. With the code as it's written right now, however, you'll then run into the opposite problem: multiple definitions of main. You'll need/want to eliminate one (undoubtedly the one in point.c).
In a larger program, you typically compile and link separately to avoid re-compiling anything that hasn't changed. You normally specify what needs to be done via a makefile, and use make to do the work. In this case you'd have something like this:
OBJS=testpoint.o point.o
testpoint.exe: $(OBJS)
gcc $(OJBS)
The first is just a macro for the names of the object files. You get it expanded with $(OBJS). The second is a rule to tell make 1) that the executable depends on the object files, and 2) telling it how to create the executable when/if it's out of date compared to an object file.
Most versions of make (including the one in MinGW I'm pretty sure) have a built-in "implicit rule" to tell them how to create an object file from a C source file. It normally looks roughly like this:
.c.o:
$(CC) -c $(CFLAGS) $<
This assumes the name of the C compiler is in a macro named CC (implicitly defined like CC=gcc) and allows you to specify any flags you care about in a macro named CFLAGS (e.g., CFLAGS=-O3 to turn on optimization) and $< is a special macro that expands to the name of the source file.
You typically store this in a file named Makefile, and to build your program, you just type make at the command line. It implicitly looks for a file named Makefile, and runs whatever rules it contains.
The good point of this is that make automatically looks at the timestamps on the files, so it will only re-compile the files that have changed since the last time you compiled them (i.e., files where the ".c" file has a more recent time-stamp than the matching ".o" file).
Also note that 1) there are lots of variations in how to use make when it comes to large projects, and 2) there are also lots of alternatives to make. I've only hit on the bare minimum of high points here.
I had this issue recently. In my case, I had my IDE set to choose which compiler (C or C++) to use on each file according to its extension, and I was trying to call a C function (i.e. from a .c file) from C++ code.
The .h file for the C function wasn't wrapped in this sort of guard:
#ifdef __cplusplus
extern "C" {
#endif
// all of your legacy C code here
#ifdef __cplusplus
}
#endif
I could've added that, but I didn't want to modify it, so I just included it in my C++ file like so:
extern "C" {
#include "legacy_C_header.h"
}
(Hat tip to UncaAlby for his clear explanation of the effect of extern "C".)
I think the problem is that when you're trying to compile testpoint.c, it includes point.h but it doesn't know about point.c. Since point.c has the definition for create, not having point.c will cause the compilation to fail.
I'm not familiar with MinGW, but you need to tell the compiler to look for point.c. For example with gcc you might do this:
gcc point.c testpoint.c
As others have pointed out, you also need to remove one of your main functions, since you can only have one.
Add the "extern" keyword to the function definitions in point.h
I saw here that this question
In c programming language, i keep getting this error
has been answered here so the thread seems closed for answers.
I disagree. It is different code.
The answer should be that we don't know what is in custom header file "functions.h".
Also, we don't know what are
MAPA m;
POSICAO heroi;
Are these functions, constants?
If these were some constants, one should expect #define in front of them, and no semicolon e.g.
#define MAPA m
#define POSICAO heroi
If You intended to prototype the function, since there's is semicolon behing, than You did not insert the parentheses ().
In that case MAPA and POSICAO are some custom-type functions, whose content should be determined in "Functions.h"
Also, there's a possibilty that You wanted to import the functions or variable or constant from some other directory, and in that case You're missing the word
extern MAPA m;
I had a similar problem running a bunch of .c files in a directory all linking to one header file with custom function prototypes.
I ran:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c
Getting these errors:
/usr/bin/ld: /tmp/ccovH4zH.o: in function `_puts': 3-puts.c:(.text+0x2f): undefined reference to `_putchar'
/usr/bin/ld: 3-puts.c:(.text+0x51): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o: in function `main': _putchar.c:(.text+0xe): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x18): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x22): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o:_putchar.c:(.text+0x2c): more undefined references to `_putchar' follow
collect2: error: ld returned 1 exit status
Note: All files were linked to the same header file with all the function declarations.
I manage to compile successfully after adding -c option to the gcc compiler like:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 -c *.c
This run successfully.
Just in case anyone comes across the same.
I'm new to strong & weak symbol concepts. For the following example (pure C) code, x is defined twice, one strong and one weak. I'd like to make my compiler report error:
foo.c:
#include <stdio.h>
void f(void);
int x = 15213;
int main(){
f();
printf("x = %d\n", x);
return 0;
}
bar.c
int x;
void f(){
x = 15212;
}
For gcc, "-fno-common" is what I want:
gcc -o foobar foo.c bar.c -fno-common
Thus it reports redefined symbols (x).
Is there an equivalent compile option in Visual Studio? (Correct me if I'm wrong described)
This is a link option: not a compile option. The compiler doesn't know anything about x being declared anywhere else except in the file it is compiling. The linker, however, sees two x declarations and will generate error 2005 or 1169.
I have three files, test.c, a.h, a.c. test.c call a function declared in a.h, and a.c define the function. But the funcion in a.c are different from a.h in the return value and the parameter. Either case, there is no warning from my gcc and there is some result. Why?
In my test.c
#include "a.h"
#include <stdio.h>
int main(){
int x = a();
printf("%d\n", x);
}
In my a.h
int a();
In my a.c
#include <stdio.h>
void a(int a)
{
printf("%d\n", a);
}
in my terminal:
$ gcc -o test test.c a.c // no warning
$ ./test
1
2
Without the a.h being included in a.c, the compiler doesn't know it's a problem. So you won't get any compile issues at all. Each gets its own .o file and everyone is happy.
The compiler expects a() to return an int so it has the machine code grab the result off the stack (or probably some register).
The compiler expects a() to have a parameter, so it has the machine code grab the parameter off the stack (again, probably a register).
Then the linker comes along and puts them all together. It doesn't know that there's an issue, but it makes the call to a() work.
So you get values that are left over on the register (or stack). And hopefully you're in a protected environment so that you're not getting some other user's information.
I have written a C program, which consists below given three files in same directory
main.c
#include<stdio.h>
#include "test.h"
int main()
{
int b=0;
b = test_add(3,2);
printf("Added: b=%d\n\n",b);
return 0;
}
test.h
int test_add(int a, int b);
test.c
int test_add(int a, int b, int c)
{
return a+b+c;
}
I am compiling the program using below command:
$gcc -Wall -Wextra main.c test.c
It compiles successfully. I can see there is mismatch in number of arguments of calling function and its actual definition. Compiler doesn't give any warning/error for such problem. How can this type of errors be reported by compiler?
This shows one of the oddities of the C standard. It allows entities such as functions to be undefined.
The actual error is that you did not
#include "test.h"
in you test.c file.
That means that the main file only sees the version of the function with three parameters. When it reaches the function call, it implicitly declares the function with two parameters.
When you run it, you get bogus values for b. I am guessing the superuser's password could somehow be in there ;)
If you add the include directive, you get an error at compile time.
What worries me, that there is no warning, not even with -Wall -Wextra -pedantic.
I had a problem with a part of my code, which after some iterations seemed to read NaN as value of a double of a struct. I think I found the error, but am still wondering why gcc (version 3.2.3 on a embedded Linux with busybox) did not warn me. Here are the important parts of the code:
A c file and its header for functions to acquire data over USB:
// usb_control.h
typedef struct{
double mean;
short *values;
} DATA_POINTS;
typedef struct{
int size;
DATA_POINTS *channel1;
//....7 more channels
} DATA_STRUCT;
DATA_STRUCT *create_data_struct(int N); // N values per channel
int free_data_struct(DATA_STRUCT *data);
int aqcu_data(DATA_STRUCT *data, int N);
A c and header file with helper function (math, bitshift,etc...):
// helper.h
int mean(DATA_STRUCT *data);
// helper.c (this is where the error is obviously)
double mean(DATA_STRUCT *data)
{
// sum in for loop
data->channel1->mean = sum/data->N;
// ...7 more channels
// a printf here displayed the mean values corretly
}
The main file
// main.c
#include "helper.h"
#include "usb_control.h"
// Allocate space for data struct
DATA_STRUCT *data = create_data_struct(N);
// get data for different delays
for (delay = 0; delay < 500; delay += pw){
acqu_data(data, N);
mean(data);
printf("%.2f",data->channel1->mean); // done for all 8 channels
// printf of the mean values first is correct. Than after 5 iterations
// it is always NaN for channel1. The other channels are displayed correctly;
}
There were no segfaults nor any other missbehavior, just the NaN for channel1 in the main file.
After finding the error, which was not easy, it was of course east to fix. The return type of mean(){} was wrong in the definition. Instead of double mean() it has to be int mean() as the prototype defines. When all the functions are put into one file, gcc warns me that there is a redefinition of the function mean(). But as I compile each c file seperately and link them afterwards gcc seems to miss that.
So my questions would be. Why didn't I get any warnings, even non with gcc -Wall? Or is there still another error hidden which is just not causing problems now?
Regards,
christian
When each .c file is compiled separately, the only information the compiler knows is the function prototype you have given.
Because every file is compiled separately, there is no way the compiler process of main.c knows the definition of mean in helper.c is wrong.
After the .c file is compiled, the signature will be stripped, so the linker cannot know the mean is wrong either.
A simple fix is always include the interface .h file in the implementation .c file
// in helper.c:
#include "helper.h"
double mean(DATA_STRUCT *data);
Then the compiler process of helper.c will notice that inconsistent type and warn you.
A mean usually is a real value so double is ok. Here you define mean as returning double, but the prototype says int mean(...).
The only way gcc can be aware of the fact that there's a redefinition, is if the redefinition occurs for real... When you compile files separately likely the mean prototype is missing... it is not shown in your code fragment at least: you should include helper.h also into helper.c. Doing so, gcc -c helper.c must give you a warning. I have gcc 4.3.2, but I am almost sure it must be so also for the version you have. In the main, you just use mean, so here the gcc trusts what is said in helper.h. When you link, there is no more information about the size of arguments and returning value, and bad things happen (like reading an int as a double).
Another detail: you say you get NaN for an int of the struct... well, in the struct there's a double, and int can't be NaN!