Instead of declaring a function pointer typedef for a function, is it possible to get it from the function declaration?
Typically,
int foo(int x);
typedef int (*fooFunc)(int);
fooFunc aFunc;
What I want:
int foo(int x);
foo* aFunc;
I want to use it for dlsym:
foo* aFunc;
aFunc = dlsym(lib, "foo");
aFunc(x);
If I update foo and forgot to update fooFunc, or vice versa, that would be bad. Also, I may have many functions and it would be more work to maintain both the function declarations and the function pointer typedefs that are associated with those functions.
Conclusion:
AndreyT's answer is the most portable but if you code for gcc then typeof is a great solution.
If you are talking about a declaration specifically, i.e. a non-defining declaration of a function, you can remove the redundancy by defining a typedef-name for function type and using it in both cases - to declare the function itself and to declare a pointer to it, like this
typedef int FuncType(int); /* <- function type */
FuncType foo; /* <- declaration of `int foo(int)` */
FuncType *aFunc; /* <- definition of `int (*aFunc)(int)` */
I.e. typedef-names can be used in non-defining function declarations. However, you can't use a typedef name in function definition, meaning that later you'll still have to do
int foo(int x) /* <- no way to use the above `FuncType` here */
{
/* whatever */
}
which basically renders the above trick virtually useless.
Of course, this doesn't help you to generate a pointer from an existing non-modifiable function declaration, if that's your situation.
If you have gcc, typeof works.
Update
$ cat fxf.c
#include <stdio.h>
int main(int argc, char **argv) {
typedef __typeof__ (main) function_of_same_type_as_main_t;
function_of_same_type_as_main_t *f;
printf("main() called.\n");
f = main;
if (argc) f(0, NULL);
return 0;
}
$ /usr/bin/gcc -std=c89 -pedantic -Wall -Wextra -o fxf fxf.c
fxf.c:3: warning: unused parameter ‘argv’
$ ./fxf
main() called.
main() called.
Simple answer: no, that doesn’t work. foo is a specific function which has a prototype (int (int)). Using foo in the way you did would be a bit like using an int to declare another int:
4 x; // expect this to be the same as int x
That said, there might be compiler extensions which make that work. I know that the upcoming C++ standard will have the decltype keyword to allow that. Using that, the following might work (untested, since I don’t have a supporting compiler handy):
int foo(int x);
decltype(&foo) aFunc = dlsym(lib, "foo");
It is not possible. However, you can write some code that would generate a warning, so that you would catch type mismatch. The following code generates an assignment from incompatible pointer type warning.
#include <stdio.h>
int foo(int, int);
typedef int(*fooFunc)(int);
fooFunc myfunc;
int foo(int x, int y)
{
return 2*x + y;
}
int main(int argc, char **argv)
{
myfunc = foo;
printf("myfunc : 0x%x\n", (unsigned int)myfunc);
return 0;
}
Of course, this means you would have to write this test code where the foo function is visible, so this is still more code to add for each function type. The solution here is probably a code generator, that would generate a proper header file containing both functions and their associated typedefs
Not quite the same, but you can typedef the function and use it for both the prototype and the pointer.
typedef int fooFunc(int);
fooFunc foo;
fooFunc *aFunc;
Related
main.h
struct tagname {
int m1;
int m2;
};
main.c
#include "main.h"
int main(void) {
struct tagname d1;
d1.m1 = 7;
struct tagname {
float s1;
float s2;
float s3;
};
struct tagname e1;
e1.s1 = 0;
}
I am using XC16 v1.60 (which I believe uses GCC v4.5.1 as the base) with -Wall, -Wextra, -Wshadow, and a host of other flags which I don't think are relevant, and I would have thought (hoped?) that the compiler would issue a warning here. What am I missing?
Edit: Apologies, I have updated the question with the extra detail desired.
C allows new declarations of identifiers in new scopes. When you declare a function or start a compound statement with {, that starts a new scope. Iteration and selection statements also start new scopes. Inside a new scope, a new declaration of an identifier generally hides the previous declaration. Since this is legal C, the compiler allows this.
In GCC 4.5.1, the documentation for -Wshadow says it warns “whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed.” A structure tag is not a local variable or a built-in function.
Incidentally, the return type of main should be int except in special situations; using int main(void) or int main(int argc, char *argv), not void main(void).
There are a lot of questions out there about forward declarations and opaque types, but most seem to be from the perspective of the library author, or people trying to use incomplete types without pointers or some such.
I'm using a library whose interface accepts/returns FOO * pointers. I'd like to confirm that I cannot (or should not) somehow forward-declare FOO or FOO * in my header file (which defines a struct with a FOO * member).
I do know that I could just #include <library.h> in both my header and my .c file, but since this is really just a learning project, I wanted to get clarification. (On the one hand, it seems like a forward-declaration might be possible, since my struct member is only a pointer and thus its size is known without knowing what FOO is—but on the other hand, I don't know if it's valid/smart to typedef something to FOO when the library is already doing that.)
Thanks in advance!
Assuming you never need to dereference the pointer, then you can use an opaque type pointer if you know the struct tag name for it:
typedef struct FOO FOO;
You can now create FOO * variables, and use them. And you probably could find the structure tag from the header file, but you should be aware that the library owners could change it at any time.
It is still usually best to include the official header, but if most of your code is not accessing the actual library, just passing around a handle to something returned by the library, you can avoid the 'cost' of including the actual header. You should measure what that cost is before deciding on what is probably premature optimization. It might be argued that if you have to ask the question, you don't know enough to be sure of doing it right, and you're in danger of getting burnt.
Note that you cannot create actual variables of the type; for that to work, the compiler needs to know how big the structure actually is, which means you need the details from the header.
Strictly speaking, if you don't know the tag name, that won't work. And likewise, if the structure doesn't have a tag, you can't do it either. And if it isn't a structure type, you can't do it.
Note that if you know the structure tag, you can also write:
struct FOO *fp;
If you have to get inventive, everything works for passing around pointers until you reach the point where you need to access the actual library functions. Then you need the actual library header (to make sure the information is right), and if your structure tag is wrong, all hell breaks loose. So, if you're going to play this game, make sure you get the structure tag correct.
Note that C11 allows a typedef to be repeated as long as it is the same each time, whereas earlier versions of C did not allow that. This can be a considerable help.
Working example
This is close to a minimal example that shows how it might be done. It assumes C11 where the repeated typedef is legitimate. It won't work for C99 or C89/C90 because the typedef for FOO is repeated when projfunc.c is compiled. (There are various ways you can adapt it so that it will work in C99 or earlier, but they're messier, using #ifdef or similar around the project.h typedef — since the presumption is that you can't alter library.h; if you can, it is part of your project after all.)
The project.h header is used primarily by the general code that belongs to the project that uses the library defining FOO — which is represented by projmain.c in this example. It can be used on its own, or with library.h, which is illustrated by projfunc.c which is the project code that actually interfaces to the library and makes calls to the library. The file library.c only uses library.h.
You can play with alternative declarations of FOO in project.h to see what goes wrong where. For example, typedef struct BAR FOO; will fail; so will typedef struct FOO *FOO;.
project.h
#ifndef PROJECT_H_INCLUDED
#define PROJECT_H_INCLUDED
typedef struct FOO FOO;
typedef struct Project
{
FOO *foop;
char *name;
int max;
double ratio;
} Project;
extern int proj_function(Project *pj);
#endif /* PROJECT_H_INCLUDED */
library.h
#ifndef LIBRARY_H_INCLUDED
#define LIBRARY_H_INCLUDED
typedef struct FOO
{
int x;
int y;
} FOO;
extern FOO *foo_open(const char *file);
extern int foo_close(FOO *foop);
extern int foo_read(FOO *foop, int *x, int *y);
extern int foo_write(FOO *foop, int x, int y);
#endif /* LIBRARY_H_INCLUDED */
projmain.c
#include "project.h"
int main(void)
{
Project pj = { 0, 0, 0, 0.0 };
if (proj_function(&pj) != 0)
return 1;
return 0;
}
projfunc.c
#include "project.h"
#include "library.h"
#include <stdio.h>
int proj_function(Project *pj)
{
int x, y;
pj->foop = foo_open("classic-mode");
if (foo_write(pj->foop, 1, 2) < 0)
{
foo_close(pj->foop);
return -1;
}
if (foo_read(pj->foop, &x, &y) < 0)
{
foo_close(pj->foop);
return -1;
}
printf("x = %d, y = %d\n", x, y);
return 0;
}
library.c
#include "library.h"
#include <assert.h>
static FOO foo = { 0, 0 };
FOO *foo_open(const char *file)
{
assert(file != 0);
return &foo;
}
int foo_close(FOO *foop)
{
assert(foop == &foo);
foo.x = foo.y = 0;
return 0;
}
int foo_read(FOO *foop, int *x, int *y)
{
assert(foop == &foo);
*x = foop->x + 1;
*y = foo.y + 1;
return 0;
}
int foo_write(FOO *foop, int x, int y)
{
assert(foop == &foo);
foo.x = x + 1;
foop->y = y + 2;
return 0;
}
The library should define FOO for you, either opaquely or transparently, as it's own source refers to FOO.
#include <library.h> should get you the prototypes to the functions the library provides, and also the types needed to interact with them.
If you create your own FOO type, you'll almost certainly get a compile error indicating multiple definition of 'FOO' when you include the function prototypes from the library.
So I'm working through this chapter of a sweet modern OpenGL tutorial, and in part of the code I assign a void pointer variable to the return value of a void * function from a second file. I got this error from gcc: initialization makes pointer from integer without a cast. As a test, I tried merging the two files and compiling again. This time, with the function in the same file as where it's called, I get no error.
I was able to reproduce this with three minimal files:
file1.c
void main() {
void *newval = foo();
}
file2.c
#include <stdlib.h>
void *foo() {
void *val;
val = malloc(10);
return val;
}
file3.c
#include <stdlib.h>
void *foo() {
void *val;
val = malloc(10);
return val;
}
void main() {
void *newval = foo();
}
file3.c is just the first two combined. My question is why when I compile one way I get an error, and the other way I get none:
$gcc file1.c file2.cfile1.c: In function ‘main’: file1.c:2:17:
warning: initialization makes pointer from integer without a cast
[enabled by default]$gcc file3.c$
I thought that the file1.c + file2.c combo was identical to file3.c. What am I missing?
In your file1.c, it seems the declaration of void *foo() is missing.
You can either include the header file containing this declaration or add line void *foo() on top of file1.c.
When compiler finds symbol foo followed by ( in main file, and there was no declaration, it assumes foo accepts any number of arguments and returns an int. So you see the warning that int is being converted to a pointer.
But in file file3.c, symbol foo is known as it is a defined function before its first usage so compiler knows that foo returns a pointer and thus no warning.
You need to declare the foo() function so that compiler knows what it is when it compiles file1.c.
Create file2.h and add in it
void *foo();
add include it in file.c
#include "file2.h"
Without declaration, the compiler assumes all unknown functions as returning int, but as your function returns void * and you are assigning it to void *, its trying to assign int to void * and hence you are getting that warning.
I'm having trouble assigning a passing a pointer of struct to a function my code (put simply) is
struct userCom{
int x;
int y;
}
main(void){
struct userCom com;
userComFunction(com);
printf("%d", com.x);
}
userComFunction(struct userCom *return_type){
struct userCom temp;
temp.x = 10;
printf("%d", temp.x);
*return_type = temp;
}
It would print
10
11537460
Am I passing through the pointer wrong?
I cannot seem to figure out why com.x is not equal to 10
As others have pointed out, the problem is that you're passing the wrong type of argument to userComFunction. But the real problem is that your compiler isn't telling you that.
As of C90 (that's two standards ago), calling a function with no visible declaration was legal, and the compiler would make assumptions (often incorrect) about what the function actually looks like. When the compiler sees the call to userComFunction, it hasn't seen a declaration or definition for userComFunction, so it can't diagnose your error.
As of C99, calling a function with no visible declaration is a constraint violation, meaning that a compiler must at least warn you about it. C99 also dropped the "implicit int" rule, so you can no longer omit the return type in a function declaration; main should be declared with an int return type (not void!), and userComFunction, since it doesn't return anything, should be void.
You can either move the full definition of userComFunction above the definition of main, or you can leave the definition where it is and add a "forward" declaration:
void userComFunction(struct userCom *return_type);
int main(void) {
/* ... */
}
void userComFunction(struct userCom *return_type) {
/* ... */
}
When you do that, the compiler should let you know that your call:
userComFunction(com);
is incorrect. (The fix is to change com to &com.)
You should also use gcc's command-line options to enable more warnings. For example:
gcc -std=c99 -pedantic -Wall -Wextra
-std=c99 says to enforce ISO C99 rules. -pedantic says to really enforce those rules. -Wall and -Wextra enable additional warnings.
If you want to assign 10 to x,then you should do it this way.
Here is the correct code-
struct userCom{
int x;
int y;
}
void struct userComFunction(struct userCom*);
main(void)
{
struct userCom com;
userComFunction(&com);
printf("%d\n", com.x);
}
userComFunction(struct userCom *return_type){
struct userCom temp;
temp.x = 10;
printf("%d\n", temp.x);
return_type->x= temp.x;
}
I have a RefTables.pc file.
When I execute the make command, I get this warning:
RefTables.c:109: warning: type defaults to `int' in declaration of `sqlcxt'
RefTables.c:111: warning: type defaults to `int' in declaration of `sqlcx2t'
RefTables.c:113: warning: type defaults to `int' in declaration of `sqlbuft'
RefTables.c:114: warning: type defaults to `int' in declaration of `sqlgs2t'
RefTables.c:115: warning: type defaults to `int' in declaration of `sqlorat'
How can I remove it?
I am using linux & gcc compiler.
It's been a while since I used Pro*C, but I think you can add a command line option to the proc command line
code=ANSI_C
which will give prototypes for the functions named.
You can remove the warning by specifying the type of the 5 offending declarations. Actually, they must be declared with no type at all, which defaults to int in C (but generates a warning).
Edit: I found on Google this declaration.
extern sqlcxt (/*_ void **, unsigned int *, struct sqlexd *, struct sqlcxp * _*/);
The function has no return type. It should have one. Write it as follows.
extern int sqlcxt (/*_ void **, unsigned int *, struct sqlexd *, struct sqlcxp * _*/);
Or you can manually state in the compiler command line to ignore these warnings. They won't be displayed anymore.
In the future, provide a code snippet along with the warnings so that we have some context to work from. Otherwise we can only guess at what the real problem is.
I'm assuming that sqlcxt, sqlcx2t, etc., are functions. Without seeing the source code, it sounds like you don't have a declaration for those functions in scope before using them.
Here's a short example of what I mean:
int main(void)
{
foo();
return 0;
}
void foo(void)
{
// do something interesting
}
When the compiler sees the call to foo in main, it doesn't have a declaration in scope, so it assumes that foo returns int, not void, and will return a warning similar to what you got above.
If your functions are defined in the same file as they are called, there are two ways around this problem. My preferred way is to define the function before it is used:
void foo(void)
{
// do something interesting
}
int main(void)
{
foo();
return 0;
}
Another way is to have a declaration of the function in scope before calling it:
void foo(void);
int main(void)
{
foo();
return 0;
}
void foo(void)
{
// do something interesting
}
It sounds like these functions are part of a database API; if so, there should be a header file that contains declarations for those functions, and that header should be included in your source file:
/** foo.c */
#include "foo.h"
void foo(void)
{
// do something interesting
}
/** end foo.c */
/** foo.h */
#ifndef FOO_H
#define FOO_H
void foo(void);
#endif
/** end foo.h */
/** main.c */
#include "foo.h"
int main(void)
{
foo();
return 0;
}
/** end main.c */
Hope that helps.