Issue passing a function as a parameter in C - c

I'm new to C and stuck on this. The answer here seems widely accepted, but I believe I'm following the correct format and still getting issues.
Here's the offending line in main() (in main.c)
PrintWrapper(PrintFunction, *decoded); // *decoded is a char
The PrintFunction (also in main.c):
void PrintFunction(char c)
{
printf("%c", c);
}
And the prototype declaration (in p1a2.h - in the same directory as main.c)
extern void PrintWrapper(void (*)(char), char c);
The actual source is hidden away in printwrapper.o (same directory as main.c). This is for an assignment and is a very contrived usage of passing a function as a parameter. I compile the program with
g++ main.c printwrapper.o -Wall -g -o tnine
and get the compiler error (the backtick is not a typo if that is relevant)
<path>/main.c:42: undefined reference to `PrintWrapper(void (*)(char), char'
Why does this happen? I'm hoping it's me overlooking something simple.

As you are using g++, the compiler expects the function name to be mangled (for more information see this wikipedia article.
To fix the issue, use gcc instead of g++ or try the following:
extern "C" void PrintWrapper(void (*)(char), char*);

The code you showed us is valid.
Looks like printwrapper.o just don't contain such function.

You should use gcc instead of g++ to compile C code. The latter front-end is for C++ code, which symbols are subject to name mangling. Assuming that you are really asking about C language, the proper way to compile your project is:
gcc main.c printwrapper.o -Wall -g -o tnine
Here is some working sample:
main.c
#include <stdio.h>
#include "pla2.h"
void PrintFunction(char c)
{
printf("%c\n", c);
}
int main(void)
{
char c = 'a';
char *decoded = &c;
PrintWrapper(PrintFunction, *decoded);
return 0;
}
pla2.h
extern void PrintWrapper(void (*)(char), char c);
printwrapper.c
extern void PrintWrapper(void (*f)(char), char c)
{
f(c);
}
then:
$ gcc -c printwrapper.c
$ gcc main.c printwrapper.o -Wall -g -o tnine
$ ./tnine
a

Related

Use of extern variable in c

I have made two files in c i.e. file1.c file2.c. In file1.c I wrote
#include< stdio.h >
int s=10;
void main()
{
printf("This is file 1");
}
In file2.c
include < stdio.h >
extern int s;
void main() {
printf("%d",s);
}
When I compiled file2.c in ubuntu terminal I got undefined referenced to s error.
How can I resolve this error?
In the second case,
extern int s;
tells the compiler that "somewhere there" exists a variable s which has type int, but it actually does not "define" the variable. So, the linker has no clue where to find the variable, it cannot find the variable and throws the error.
You need to have a definition of the variable, either in a separate translation unit (the purpose of using extern) or in the same translation unit (if you want).
In file1.c
#include <stdio.h>
void myfunction( void );
int s=10;
void myfunction()
{
printf("This is file 1");
}
In file2.c
#include <stdio.h>
void myfunction( void );
extern int s;
int main( void )
{
myfunction();
printf("%d",s);
}
then compile (the example uses gcc
gcc -g -Wall -Wextra -pedantic -Wconversion -std=gnu11 -c file1.c -o file1.o
gcc -g -Wall -Wextra -pedantic -Wconversion -std=gnu11 -c file2.c -o file2.o
then link using:
gcc -g file1.o file2.o -o myexec
then run it as
./myexec
Of course, if your using Visual Studio, the command line statements will be slightly different

Why is Xcode allowing me to declare C variables anywhere?

I created a basic C project in Xcode and modified the starter code in main.c slightly. I also went into the build settings and told it to use ANSI-C. Here's the code I have:
int main(int argc, const char * argv[])
{
// a statement!
printf("Hello, World!\n");
// shouldn't this cause a compiler error?
// the variable isn't declared at the top of the scope.
int x;
x += 10;
return 0;
}
Obviously, it doesn't do much, but I expected the variable declaration to produce a compiler error (since older versions of C require variable declarations at the beginning of the scope, before other statements). However, Xcode happily compiles it and runs it with neither an error or warning.
I might be making a dumb mistake somewhere, but I'm trying to understand why this code compiles. I've read that C99 and C11 allow you to declare variables anywhere, so this would work, but I explicitly set the project to use ANSI-C. Is this just the way Apple's LLVM compiler works? Or am I missing something elsewhere?
TL;DR You need to add -pedantic (or -Wdeclaration-after-statement) to -ansi to get the warning you want.
Somewhat to my surprise, both clang (from Apple XCode 7.2) and gcc (from GCC 5.3.0, which I built), accept the code when compiled with either -std=c90 or -ansi even though it is not strictly compliant with C90.
However, both complain when told to be -pedantic.
$ clang -ansi -c xyz.c
$ clang -std=c90 -c xyz.c
$ gcc -std=c90 -c xyz.c
$ which gcc
/opt/gcc/v5.3.0/bin/gcc
$ gcc -std=c90 -pedantic -c xyz.c
xyz.c: In function ‘main’:
xyz.c:7:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int x;
^
$ clang -pedantic -std=c90 -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$ clang -pedantic -ansi -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$
The file xyz.c is your source code with the comments stripped, #include <stdio.h> added at the top, and int main(void) in place of int main(int argc, char **argv) since the code doesn't use the arguments.
Note that your code has undefined behaviour; incrementing an uninitialized variable is a bad idea.

Implicit declaration of function ‘str[n]casecmp’ [-Werror=implicit-function-declaration]

I am compiling a C library, using C99. I am including string.h to my translation unit (and I can navigate to the definitions of the str?casecmp functions in my NetBeans IDE.
The source looks something like this:
#include <string.h>
int foo(char* c1, char* c2) {
return strcasecmp(c1, c2);
}
int foobar(char* c1, char* c2, int n) {
return strncasecmp(c1, c2, n);
}
However, when I attempt to compile, I get the error shown in the title.
I am using GCC version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5).
This is what my gcc command looks like:
gcc -c -g -Werror -DE4C_THREADSAFE -DLINUX_BUILD -I../include -I../genutils -std=c99 -fPIC -MMD -MP -MF build/Debug/GNU-Linux-x86/btypes.o.d -o build/Debug/GNU-Linux-x86/btypes.o btypes.c
What is causing this, and how do I fix it?
These functions are declared in strings.h, not string.h.
Include the header strings.h instead of string.h.

Error when compiling with GCC

Every time I compile I get the following error message:
Undefined reference to ( function name )
Let's say I have three files: Main.c, printhello.h, printhello.c. Main.c calls function print_hello(), which returns "Hello World". The function is defined in printhello.c.
Now, here's the following code of printhello.h:
#ifndef PRINTHELLO_H
#define PRINTHELLO_H
void print_hello();
#endif
I am sure this code is fine. I still don't know why is it giving me the error, though. Can you help me?
Undefined references are the linker errors. Are you compiling and linking all the source files ? Since the main.c calls print_hello(), linker should see the definition of it.
gcc Main.c printhello.c -o a.out
The error is, I think, a linker error rather than a compiler error; it is trying to tell you that you've not provided all the functions that are needed to make a complete program.
You need to compile the program like this:
gcc -o printhello Main.c printhello.c
This assumes that your file Main.c is something like:
#include "printhello.h"
int main(void)
{
print_hello();
return 0;
}
and that your file printhello.c is something like:
#include "printhello.h"
#include <stdio.h>
void print_hello(void)
{
puts("Hello World");
}
Your declaration in printhello.h should be:
void print_hello(void);
This explicitly says that the function takes no parameters. The declaration with the empty brackets means "there is a function print_hello() which returns no value and takes an indeterminate (but not variadic) list of arguments", which is quite different. In particular, you could call print_hello() with any number of arguments and the compiler could not reject the program.
Note that C++ treats the empty argument list the same as void print_hello(void); (so it would ensure that calls to print_hello() include no arguments), but C++ is not the same as C.
Another way to do it is to explicitly build object files for the printhello:
gcc -c printhello.c -o printhello.o
gcc -o Main main.c printhello.o
This has the added benefit of allowing other programs to use the print_hello method
It seems that the error is from the linker and not the compiler. You need to compile and link both the source files. I think what you are doing is simply including the header file in Main.c and you are not compiling the printhello.c
You need to :
gcc Main.c printhello.c -o myprog
or
construct the object files first
gcc -c printhello.c
gcc -c Main.c
then link them
gcc Main.o printhello.o

Why does CC not see my function definition in header?

I'm writing a simple application in ANSI C. I am using GCC in a Unix environment.
I have the following sample application:
//main.c
#include "foo.h"
int main()
{
int result;
result = add(1,5);
return0;
}
Header:
//foo.h
#ifndef FOO_H_INCLUDED
#define FF_H_INCLUDED
int add(int a, int b);
#endif
Implementation:
//foo.c
int add(int a, int b)
{
return a+b;
}
I am compiling my program with the following command:
cc main.c -o main.o
The compiler complains that 'reference to add is undefined'. Is this a linking problem? How do properly make use of my header?
Thanks!
You need to compile both your source files together:
cc main.c foo.c -o main
Also, in this case, -o produces an executable, so calling it main.o can be misleading.
Yet another tidbit, though unrelated to the question: the #ifndef and #define in foo.h don't match.
The header is not your current problem. Your current problem is that you're not compiling the add function definition in foo.c.
Try
cc main.c foo.c -o main.o
If you are trying to compile main.c into an assembled object file, you need to prevent gcc from trying to link. This is done via
cc -c main.c -o main.o
You can compile all other object files, then when you have all of your object files ready, you simply do
cc main.o obj1.o anotherOBJ.o -o myExecutableBinary
"undefined reference" is a linker error, not a compiler error.
The compiler sees the declaration in the header, but you have not compiled or linked the definition in foo.c. Your title uses the term definition incorrectly.

Resources