I define a structure that I call Neuron.
In my main, I create a two dimensional array:
Neuron N_network[4][10]; //create a neural network
I have a function to print the structure element:
void print_stat_neuron(Neuron * neuron_info)
What should I write to print N_network[i][j] (as an argument of the print_stat_neuron() function)?
I try simply with &(N_network[i][j]) and I get an error message.
I have the fallowing error message with the compiler gcc -Wall -Wextra:
2ex4.c: In function 'init_network':
2ex4.c:168:2: warning: implicit declaration of function'print_stat_neuron' [-Wimplicit-function-declaration]
print_stat_neuron(&N_network[4][1]);
^
2ex4.c: At top level:
2ex4.c:191:6: warning: conflicting types for 'print_stat_neuron' [enabled by default]
void print_stat_neuron(Neuron * neuron_info)
^
2ex4.c:168:2: note: previous implicit declaration of 'print_stat_neuron' was here
print_stat_neuron(&N_network[4][1]);
You need to change the parameter to Neuron (*neuron_info)[10]. Now you can call this function as
print_stat_neuron(N_network);
or
print_stat_neuron(&N_network[0]);
The error messages you show come from not declaring the function before using it, so the compiler deduces a type for the function (extern int print_stat_neuron(); with no specification for the number or types of the parameters), and then objects to you defining it with a return type of void. Note that in C, extern int print_stat_neuron(); is not a prototype for a function with no arguments; that's extern int print_stat_neuron(void);.
This code compiles cleanly:
typedef struct Neuron
{
int x;
} Neuron;
void print_stat_neuron(Neuron *neuron_info);
int main(void)
{
Neuron N_network[4][10];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 10; j++)
print_stat_neuron(&N_network[i][j]);
}
return 0;
}
This declares the function before using it. It would also be acceptable to define the function before using it (which saves having a separate declaration). Of course, if the function will be used outside the source file where it is defined, it should have a declaration in a header, and the header should be used both where it is defined and where it is used. If the function is not used outside the source file where it is defined, it should be static.
Clean compilation checked with GCC 5.3.0 on Mac OS X 10.10.5 (my El Capitan machine is under warranty repair, unfortunately):
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition -c neuron.c
$
Related
I have some example code. When I uncomment the invalid_call function call I get a compiler error as expected. Unfortunately, calling my_function with wrong number of arguments still compiles leading to undefined behavior (UB).
main.c
#include <linux/module.h>
#include <linux/kernel.h>
#include "header.h"
extern void my_function(int x);
static int my_init(void)
{
my_function(5);
// invalid_call( 5 ); // doesn't compile
return 0;
}
static void my_exit(void)
{
pr_info("removing module");
}
module_init(my_init);
module_exit(my_exit);
func_source.c
#include <linux/kernel.h>
void my_function(int x, int y)
{
pr_info("%d %d",x,y);
}
header.h
void invalid_call(int x, int y)
{
return;
}
Expected output:
Compiler error when calling my_function() with only one argument.
Actual output:
Code compiles and prints a random value for y, essentially UB.
I know that extern void my_function(int x); is just another declaration so I don't think compiler needs to throw an error however, when I call my_function with a single argument, it shouldn't be able to find a match to any function definition. Unfortunately, instead of a compiler error I run into UB.
How does this work? I know UB is UB but how why does it become UB. I thought the function signature mismatch would cause a compiler. My suspicion is the extern declaration but still...
Also, bonus question. How do I avoid running into this problem again? Any design patterns or practices I can follow?
Here is the Makefile if you want to test it out yourself.
obj-m += main.o
example-y := ./src/main.o ./src/func_src.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Folder structure:
./Makefile
./src/main.c
./src/my_func.c
Thanks in advance.
In C, at least, neither the compiler nor the linker has global knowledge of all the functions in all the source files of your program (or kernel module, or whatever). The compiler compiles one source file at a time, and all it has to go on is the declarations -- including the prototypes -- that are visible during that one compilation. So if the prototype is wrong -- you're doomed. The compiler validates your (incorrect) call against the (incorrect) prototype, and finds no mismatch, and so generates an (incorrect) call that passes one argument, leading to the behavior you see.
For this reason it's an excellent idea to:
never put external prototypes in .c files, but rather, in .h files, which you include wherever you call the functions, and
also include the .h file in the source file where you define the function.
That way, not only does the compiler check that the calls match the prototype, it can also check that the prototype matches the actual definition, and since there's only one copy of the prototype (in that one .h file), it's more or less impossible for it to fall out of sync and end up being incorrect. See also this question.
In your question, you seemed to think that it wouldn't even be possible for the incorrect call to be linked up with the two-argument-accepting definition. That might be true in C++, where "name mangling" arranges for a function's arguments to be part of its signature. But nothing like that happens in C. Your function's sole identity -- in the symbol table, and as far as the linker is concerned -- is the name my_function, and nothing at link time prevents a one-arg-passing call from being matched up with the two-arg-accepting definition.
Some ways to detect this problem:
building in gcc with link-time optimization will usually flag this.
Using -Wmissing-prototypes would have warned for func_source.c that you have an externally-visible function with no prototype.
You should have the correct prototype in a header file that is included by all units that want to call the function, as well as the unit containing the function definition. The latter warning flag will detect if you forget to put the prototype in the unit containing the definition (which would have caused a compilation error due to the prototype not matching the definition).
the OPs posted code results in the following messages from the compiler:
gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" (in directory: /home/richard/Documents/forum)
untitled.c: In function ‘invalid_call’:
untitled.c:1:23: warning: unused parameter ‘x’ [-Wunused-parameter]
void invalid_call(int x, int y)
^
untitled.c:1:30: warning: unused parameter ‘y’ [-Wunused-parameter]
void invalid_call(int x, int y)
^
untitled.c: In function ‘my_init’:
untitled.c:15:5: warning: implicit declaration of function ‘my_function’; did you mean ‘myFunction’? [-Wimplicit-function-declaration]
my_function(5);
^~~~~~~~~~~
myFunction
untitled.c: In function ‘my_exit’:
untitled.c:22:5: warning: implicit declaration of function ‘pr_info’ [-Wimplicit-function-declaration]
pr_info("removing module");
^~~~~~~
untitled.c: At top level:
untitled.c:25:1: warning: data definition has no type or storage class
module_init(my_init);
^~~~~~~~~~~
untitled.c:25:1: warning: type defaults to ‘int’ in declaration of ‘module_init’ [-Wimplicit-int]
untitled.c:25:1: warning: parameter names (without types) in function declaration
untitled.c:26:1: warning: data definition has no type or storage class
module_exit(my_exit);
^~~~~~~~~~~
untitled.c:26:1: warning: type defaults to ‘int’ in declaration of ‘module_exit’ [-Wimplicit-int]
untitled.c:26:1: warning: parameter names (without types) in function declaration
untitled.c:28:6: warning: conflicting types for ‘my_function’
void my_function(int x, int y)
^~~~~~~~~~~
untitled.c:15:5: note: previous implicit declaration of ‘my_function’ was here
my_function(5);
^~~~~~~~~~~
untitled.c:20:13: warning: ‘my_exit’ defined but not used [-Wunused-function]
static void my_exit(void)
^~~~~~~
untitled.c:13:12: warning: ‘my_init’ defined but not used [-Wunused-function]
static int my_init(void)
^~~~~~~
Compilation finished successfully.
Suggest enabling the warnings when compiling, then fix those warnings
I'm searching for a compiler flag for gcc and if possible for clang and the Microsoft compilers as well, that triggers a warning (error with -Werror) if a non-void function is called without using the return value like this:
int test() {
return 4;
}
int main(void) {
test(); //should trigger a warning
int number = test(); //shouldn't trigger the warning
return 0;
}
If there is no such compiler flag, maybe some way to tell the clang static analyzer to complain about it.
EDIT: To clarify my original question: I actually meant using the return value, not only assigning it.
I never used it myself (do you really need it?), you can try
defining the function with warn_unused_result attribute
enabling -Wunused-result flag with gcc.
This will tell you about any unused value from the function return.
In case, any doubts, SEE IT LIVE or SEE IT LIVE AGAIN Thanks to M.M for the link in the comment
Or:
#include <stdio.h>
extern int func1(void) __attribute__((warn_unused_result));
extern int func2(void);
int main(void)
{
func1();
int rc1 = func1();
int rc2 = func1();
func2();
printf("%d\n", rc1);
return 0;
}
Compilation (GCC 5.1.0 on Mac OS X 10.10.5):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c warn.c
warn.c: In function ‘main’:
warn.c:10:9: error: unused variable ‘rc2’ [-Werror=unused-variable]
int rc2 = func1();
^
warn.c:8:5: error: ignoring return value of ‘func1’, declared with attribute warn_unused_result [-Werror=unused-result]
func1();
^
cc1: all warnings being treated as errors
$
Some static code analyzers like splint can check for these kind of things:
$ splint check.c
Splint 3.1.2 --- 03 May 2009
check.c: (in function main)
check.c:6:5: Return value (type int) ignored: test()
Result returned by function call is not used. If this is intended, can cast
result to (void) to eliminate message. (Use -retvalint to inhibit warning)
Unlike #Sourav's answer, this does not require a specific __attribute__ annotation on the target function, but on the other hand possibly emits many warnings. Its usually possible to suppress the warnings for specific functions or function calls by using annotations (like /*#alt void#*/).
I'm developing a small library for a PID controller using avr-gcc.In spite of declaring the function in the header file and defining it separately in a .c file the compiler is throwing the following errors:
Compiling C: pid.c
avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=1000000UL -Os -funsigned-char -
funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-
adhlns=./pid.lst -std=gnu99 -MMD -MP -MF .dep/pid.o.d pid.c -o pid.o
pid.c:5: error: expected declaration specifiers or '...' before '(' token
pid.c:5: warning: function declaration isn't a prototype
pid.c:5: error: 'type name' declared as function returning a function
pid.c:5: error: conflicting types for 'PID_init'
pid.h:23: error: previous declaration of 'PID_init' was here
pid.c: In function 'PID_init':
pid.c:5: error: parameter name omitted
The header file contents of pid.h are as follows:
#include<avr/io.h>
#include<util/delay.h>
#ifndef PID_CONTROLLER
#define PID_CONTROLLER
struct PIDCONTROL
{
float error;
float prev_error;
float Kp;
float Ki;
float Kd;
float pid;
float P;
float I;
float D;
float setpoint;
};
void PID_init(float,float,float,float,struct PIDCONTROL*);
float PID(float,struct PIDCONTROL*);
#endif
The definitions for the declared functions have been made in pid.c which contains the code shown below:
#include<avr/io.h>
#include<util/delay.h>
#include "pid.h"
void PID_init(float SP,float Kp,float Ki,float Kd,struct PIDCONTROL *a)
{
a->Kp=Kp;
a->Ki=Ki;
a->Kd=Kd;
a->pid=0;
a->setpoint=SP;
a->prev_error=0;
}
float PID(float PV,struct PIDCONTROL *a)
{
a->error=(a->setpoint)-PV;
a->P=(a->Kp)*(a->error);
(a->I)+=(a->Ki)*(a->error)*1.024;
a->D=(a->Kd)*((a->error)-(a->prev_error))/1.024;
a->pid=(a->P)+(a->I)+(a->D);
a->prev_error=a->error;
return(a->pid);
}
I couldn't just figure out what's wrong with the code. Any help is appreciated.Thanks in advance.
The avr/io.h file also brings in avr/common.h which contains this little snippet:
/*
Stack pointer register.
AVR architecture 1 has no RAM, thus no stack pointer.
All other architectures do have a stack pointer. Some devices have only
less than 256 bytes of possible RAM locations (128 Bytes of SRAM
and no option for external RAM), thus SPH is officially "reserved"
for them.
*/
# ifndef SP
# define SP _SFR_MEM16(0x3D)
# endif
(it's actually a bit more complicated than that, with multiple paths depending on your architecture, but that cut down example shows what the actual problem is, at least).
It's actually defining a pre-processor macro for SP which means, when you attempt to use that in your code with a function definition along the lines of:
void PID_init(float SP,float Kp,float Ki,float Kd,struct PIDCONTROL *a)
what you'll actually get is something like:
void PID_init(float _SFR_MEM16(0x3D),float Kp,float Ki,float Kd,struct PIDCONTROL *a)
which will cause the compiler phase to complain bitterly.
I'm actually a big believer in reasonably self-describing variable names so would generally choose something more verbose than SP but you'll probably find that, even if you make it mySP, it'll fix the immediate problem.
I'm trying to run a example from the "Using Graphviz as a library" in http://www.graphviz.org/Documentation.php.
#include <gvc.h>
int main(int argc, char **argv)
{
Agraph_t *g;
Agnode_t *n, *m;
Agedge_t *e;
Agsym_t *a;
GVC_t *gvc;
/* set up a graphviz context */
gvc = gvContext();
/* parse command line args - minimally argv[0] sets layout engine */
gvParseArgs(gvc, argc, argv);
/* Create a simple digraph */
g = agopen("g", Agdirected);
n = agnode(g, "n", 1);
m = agnode(g, "m", 1);
e = agedge(g, n, m, 0, 1);
/* Set an attribute - in this case one that affects the visible rendering */
agsafeset(n, "color", "red", "");
/* Compute a layout using layout engine from command line args */
gvLayoutJobs(gvc, g);
/* Write the graph according to -T and -o options */
gvRenderJobs(gvc, g);
/* Free layout data */
gvFreeLayout(gvc, g);
/* Free graph structures */
agclose(g);
/* close output file, free context, and return number of errors */
return (gvFreeContext(gvc));
}
I'm compiling and linking with : gcc -Wall pkg-config libgvc --cflags --libs *.c -o EXE -lgvc
and then I see this result:
graph.c: In function ‘main’:
graph.c:14:18: error: ‘Agdirected’ undeclared (first use in this function)
graph.c:14:18: note: each undeclared identifier is reported only once for each function it appears in
graph.c:15:2: error: too many arguments to function ‘agnode’
In file included from /usr/include/graphviz/types.h:717:0,
from /usr/include/graphviz/gvc.h:20,
from graph.c:1:
/usr/include/graphviz/graph.h:185:22: note: declared here
graph.c:16:2: error: too many arguments to function ‘agnode’
In file included from /usr/include/graphviz/types.h:717:0,
from /usr/include/graphviz/gvc.h:20,
from graph.c:1:
/usr/include/graphviz/graph.h:185:22: note: declared here
graph.c:17:2: error: too many arguments to function ‘agedge’
In file included from /usr/include/graphviz/types.h:717:0,
from /usr/include/graphviz/gvc.h:20,
from graph.c:1:
/usr/include/graphviz/graph.h:192:22: note: declared here
graph.c:7:11: warning: unused variable ‘a’ [-Wunused-variable]
graph.c:6:12: warning: variable ‘e’ set but not used [-Wunused-but-set-variable]
Could anyone help me understand what is going on? Why the compiler is complaining about those arguments in those functions?
Thank you!!!!
I saved your code as g.c, then issued this command line
gcc -Wall `pkg-config libgvc --cflags --libs` g.c -o EXE -lgvc
that yields
g.c: In function ‘main’:
g.c:14:5: error: too few arguments to function ‘agopen’
/usr/local/include/graphviz/cgraph.h:266:18: note: declared here
g.c:7:14: warning: unused variable ‘a’ [-Wunused-variable]
g.c:6:15: warning: variable ‘e’ set but not used [-Wunused-but-set-variable]
then I added the miss parameter
g = agopen("g", Agdirected, 0);
and the miss library
gcc -Wall `pkg-config libgvc --cflags --libs` g.c -lgvc -lcgraph
now the code compile and link with just 2 warnings:
g.c: In function ‘main’:
g.c:7:14: warning: unused variable ‘a’ [-Wunused-variable]
g.c:6:15: warning: variable ‘e’ set but not used [-Wunused-but-set-variable]
I think it works because I've built graphviz from source, then pkg-config is up-to-date...
The program still need some debug, running it i get:
./a.out
There is no layout engine support for "a.out"
Use one of: circo dot fdp neato nop nop1 nop2 osage patchwork sfdp twopi
Error: Layout was not done. Missing layout plugins?
The message is because by default the layout engine use the exe name (i.e. a.out, default of gcc compile-and-link) as layout string...
This question already has answers here:
gcc will not properly include math.h
(2 answers)
Closed 9 years ago.
I'm writing a prime number finder. Mathematically, it is faster to, instead of doing for (unsigned long i = 2; i < number/2; i++) it's a lot faster, and still just as effective, to do for (unsigned long i = 2; i < sqrt(number); i++)
But it's not working. The below is my code.
// Stuff goes up here, including a function prototype and:
#include <math.h>
char isPrime (unsigned long number)
{
if (number <= 1) {
return 0;
}
long double sqrtOfNumber = sqrt(number); // Calculate once.
for (unsigned long i = 2; i < sqrtOfNumber; i++) {
if (number%i == 0) { // It has a divisor.
return 0;
}
}
// Nothing broke us yet....
return 1;
}
And then below is the error I get from GCC.
/tmp/ccFBlUz5.o: In function `isPrime':
main.c:(.text+0xb3): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Changing the type of "number" to a double causes problems with the % operator. And casting it to a double for the sqrt() call doesn't change anything.
Any advice?
Oh, and my math.h IS being imported, if I comment out that line, I get warned that there is an implicit declaration there.
main.c: In function 'isPrime':
main.c:28:2: warning: implicit declaration of function 'sqrt' [-Wimplicit-function-declaration]
long double sqrtOfNumber = sqrt(number); // Calculate once.
^
main.c:28:29: warning: incompatible implicit declaration of built-in function 'sqrt' [enabled by default]
long double sqrtOfNumber = sqrt(number); // Calculate once.
^
plus the other warning under that.
-lm needs to added to the command line after the file that requires that library for example if main.c required the math library then you would use:
gcc -x c main.c -lm
You can see a live example here, there are three command lines available in the example. One without -lm, one with -lm before the file that needs it one after the files that needs it.
For completeness sake if we refer to the gcc docs on options for Linking it says the following for -l:
[...]It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded. [...]
You need to link the math library. Use the -lm option on the command line.