Im trying to use the power of function pointers, it all went fine until i tried to make the function pointer use a 2nd argument as type int.
The code below generates an error, which is displayed below
In an header file:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
Error:
error: expected ‘)’ before ‘int’
void (*move)(Unit, int);
^
void (*move)(Unit); works all fine, which surprises me how adding an argument can cause an error.
I call my struct in a C file, by including header and then doing:
Unit units[UNITCOUNT];
units[0].move(&units[0], 1);
Update:
adding:
typedef struct UnitTag Unit
Causes the error to dissapear, however I can no longer use the function as before.
error: incompatible type for argument 1 of ‘units[i].move’
units[0].move(&units[0], 0);
^
note: expected ‘Unit’ but argument is of type ‘struct UnitTag *’
If I'm getting you, you can simply use struct keyword:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag, int);
} Unit;
void Test (struct UnitTag test1, int test2)
{
printf("Test1.x: %d\n", test1.x);
printf("Test1.y: %d\n", test1.y);
printf("Test2 : %d\n", test2);
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(units[0], 3);
}
Output:
Test1.x: 1
Test1.y: 2
Test2 : 3
If you want to pass struct by referebce, simply:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag*, int);
} Unit;
void Test (struct UnitTag *test1, int test2)
{
test1->x = 4;
test1->y = 5;
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(&units[0], 3);
printf("units[0].x: %d\n", units[0].x);
printf("units[0].y: %d\n", units[0].y);
}
Output is:
units[0].x: 4
units[0].y: 5
You need the prototype for Unit before using it.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
int main(void)
{
return 0;
}
After the clarification what you wanted to do. It probably makes more sense to give a pointer to Unit, so that the move command which returns void can change something about your object.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit *, int);
} Unit;
Unit test;
/* some function that corresponds to the interface */
void myMove(Unit *u, int i)
{
u->x = u->x + i;
}
int main(void)
{
/* initialize test struct */
test.x = 0;
test.y = 0;
test.move = myMove;
test.move(&test, 5);
printf("Values after move are (x, y) = (%i, %i).\n", test.x, test.y);
return 0;
}
Related
I'm trying to experiment with opaque data types to get an understanding of them. The main problem is that I keep getting an 'incomplete' error.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "blepz.h"
int main()
{
setfnarp(GOO,5);
int loogaboo = getfnarp(GOO);
printf("%i", loogaboo);
return 0;
}
fnarpishnoop.c
#include "blepz.h"
struct noobza {
int fnarp;
};
void setfnarp(struct noobza x, int i){
x.fnarp = i;
};
int getfnarp(struct noobza x){
return x.fnarp;
};
blepz.h
struct noobza;
void setfnarp(struct noobza x, int i);
int getfnarp(struct noobza x);
struct noobza GOO;
I clearly don't understand something here and I was hoping someone could help me figure out how opaque data types are implemented if the whole point of them is that you have a hard time finding actual code for them.
Using a struct that you haven't declared the contents of gives an "incomplete type" error, as you have already mentioned.
Instead, use a pointer to the struct and a function that returns a pointer to the struct, like this:
struct noobza;
struct noobza *create_noobza(void);
void setfnarp(struct noobza *x, int i);
int getfnarp(struct noobza *x);
struct noobza *GOO;
...
#include <stdlib.h>
#include "blepz.h"
struct noobza {
int fnarp;
};
struct noobza *create_noobza(void)
{
return calloc(1, sizeof(struct noobza));
}
void setfnarp(struct noobza *x, int i){
x->fnarp = i;
};
int getfnarp(struct noobza *x){
return x->fnarp;
};
...
#include <stdio.h>
#include <stdlib.h>
#include "blepz.h"
int main()
{
GOO = create_noobza();
setfnarp(GOO,5);
int loogaboo = getfnarp(GOO);
printf("%i", loogaboo);
return 0;
}
I'm doing an assignment for my data structures class and I have very little experience with C structures and C in general.
This is the .h file that I was given to do the assignment:
#ifndef C101IntVec
#define C101IntVec
typedef struct IntVecNode* IntVec;
static const int intInitCap = 4;
int intTop(IntVec myVec);
int intData(IntVec myVec, int i);
int intSize(IntVec myVec);
int intCapacity(IntVec myVec);
IntVec intMakeEmptyVec(void);
void intVecPush(IntVec myVec, int newE);
void intVecPop(IntVec myVec);
#endif
This is the .c implementation that I've made:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intVec.h"
typedef struct IntVecNode {
int* data;
int sz; // Number of elements that contain data
int capacity; // How much is allocated to the array
} IntVecNode;
typedef struct IntVecNode* IntVec;
//static const int intInitCap = 4;
int intTop(IntVec myVec) {
return *myVec->data;
}
int intData(IntVec myVec, int i) {
return *(myVec->data + i);
}
int intSize(IntVec myVec) {
return myVec->sz;
}
int intCapacity(IntVec myVec) {
return myVec->capacity;
}
IntVec intMakeEmptyVec(void) {
IntVec newVec = malloc(sizeof(struct IntVecNode));
newVec->data = malloc(intInitCap * sizeof(int));
newVec->sz = 0;
newVec->capacity = intInitCap;
return newVec;
}
void intVecPush(IntVec myVec, int newE) {
if (myVec->sz >= myVec->capacity) {
int newCap = myVec->capacity * 2;
myVec->data = realloc(myVec->data, newCap * sizeof(int));
} else {
for (int i = 0; i < myVec->capacity; i++) {
*(myVec->data + i) = *(myVec->data + i + 1);
}
myVec->data = &newE;
}
myVec->sz++;
}
void intVecPop(IntVec myVec) {
for (int i = 0; i < myVec->capacity; i++) {
*(myVec->data - i) = *(myVec->data - i + 1);
}
myVec->sz--;
}
This is the test file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intVec.c"
int main() {
struct IntVec v;
v.intVecPush(v,0);
return 0;
}
Every time I run the test file, I get the error:
test.c:7:16: error: variable has incomplete type 'struct IntVec'
struct IntVec v;
^
test.c:7:9: note: forward declaration of 'struct IntVec'
struct IntVec v;
^
1 error generated.
I've tried changing the #include "intVec.c" to "intVec.h" in the test file, however that produces the same error. What would I need to change in order to not get this error?
There is no structure definition struct IntVec.
So the compiler is unable to define the object v
struct IntVec v;
I think you mean
IntVec v;
And this call
v.intVecPush(v,0);
is invalid and does not make sense. I think there should be something like
IntVec v = intMakeEmptyVec();
intVecPush(v,0);
instead of
struct IntVec v;
v.intVecPush(v,0);
Also it is a bad idea to include the whole module in another module. You should place the structure definition in the header and include this header in the compilation unit with main.
That is move these definitions
typedef struct IntVecNode {
int* data;
int sz; // Number of elements that contain data
int capacity; // How much is allocated to the array
} IntVecNode;
typedef struct IntVecNode* IntVec;
in the header.
**> Is there a way to access a variable that come from other struct? When
i try this code,i am getting this compile error.
**
test.c: In function ‘readRecordsFromFile’:
test.c:70:18: error: expected expression before ‘kdnode’
printf(" %f\n",kdnode.data.latitude);
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
#define rec_size 112
typedef struct _Node kdnode;
typedef struct _Record record;
static void readRecordsFromFile(char *filename);
struct _Record{
int plateNumber;
long *name[32];
double area;
int population;
int density;
int popcitycenter;
long region;
double latitude;
double longtitude;
};
struct _Node
{
//kdnode left;
//kdnode right;
record data;
bool type;
double x;
double y;
int pagenumber;
};
int main(){
readRecordsFromFile("data.dat");
return 0;
}
static void readRecordsFromFile(char *filename)
{
FILE* inputFile;
inputFile = fopen(filename, "rb");
int i;
if(!inputFile) {
printf("Could not open file");
return;
}
int length,record_count;
fseek(inputFile,0,SEEK_END);
length=ftell(inputFile);
fseek(inputFile,0,SEEK_SET);
record_count = length/sizeof(record);
kdnode kd;
fread(&kd,rec_size,2,inputFile);
printf("%d",ftell(inputFile));
for (i = 0; i < record_count; i++)
{
printf(" %f\n",kdnode.data.latitude);
}
fclose(inputFile);
}
typedef struct _Node is typedefed as knode. knode represents a data type and it's not an identifier, so this
printf(" %f\n",kdnode.data.latitude);
has to be
printf(" %f\n", kd.data.latitude);
You should also check return values for functions like fread() for example.
In h.c file:
#include <stdlib.h>
typedef struct
{
int x;
}XS;
typedef struct
{
XS x_array[10];
}YS;
extern YS y;
In m.c file:
#include "h.c"
int void main()
{
YS y = malloc(sizeof(YS));
y.x_array[0].x = 1;
free(y);
return 0;
}
This won't compile and I cannot figure out why. Could someone shed some light on this?
your main must look like this:
#include "h.h"
int main()
{
YS *y = malloc(sizeof(YS));
y->x_array[0].x = 1;
free(y);
return 0;
}
In h.h file:
#ifndef H_H
#define H_H
#include <stdlib.h>
typedef struct
{
int x;
}XS;
typedef struct
{
XS x_array[10];
}YS;
#endif
There are multiple issues with your code:
1. In h.c, you declare YS y as extern which means the compiler expects a external global declaration for y. But you've declared it as a local object in m.c
You are trying to malloc for a static object.
h.h
#include <stdlib.h>
typedef struct
{
int x;
}XS;
typedef struct
{
XS x_array[10];
}YS;
YS *y;
m.c:
#include <stdlib.h>
#include "h.h"
extern YS *y;
int void main()
{
y = malloc(sizeof(struct YS));
y->x_array[0].x = 1;
free(y);
return 0;
}
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Other way I thought as,
struct *_my_type x = (struct _my_type *)malloc(sizeof(struct _my_type));
void_x = x
printf(Value: %d\n", x->a);
But still I'm getting seg-fault error.
ok here is the problem with void*....
e.g.
in core.c
void init_my_type(hidden_my_type a)
{
my_type *the_a = malloc(...);
a = the_a // <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this correct?! a is void* and the_a // is original type
pthread_cond_init(&the_a->...);
.. (in short any other methods for init ..)
}
void my_type_destroy(my_hidden_type x)
{
my_type *the_x = x;
pthread_detroy(&the_x-> ...);
}
in main.c
test()
{
my_hidden_type x;
init_my_type(x);
....
my_type_detroy(x);
}
this it self should fail. as in main.c test function, x is void* ... init will allocate but in destroy I'm again passing void* .. which can be anything!
EDIT (Solved for me)
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void init_hidden_type(hidden_my_type void_p_my_type)
{
struct _my_type *real_my_type = (struct _my_type *)malloc(sizeof(struct _my_type));
//--- Do init for your type ---
void_p_my_type = real_my_type;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
Version 0 — Critique of Question's Code
The posted code does not compile.
api.h
typedef void* hidden_my_type;
void do_something(my_type x);
This defines hidden_my_type but not the my_type that is passed to do_something(). Presumably, you intended:
typedef void *my_type;
void do_something(my_type x);
core.c
struct _my_type
{
int a;
}
As noted below too, there is a semi-colon missing after the structure definition.
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
You have the hidden_my_type vs my_type problem again. You have the * of the pointer where it cannot go; it must go after the struct _my_type. You probably intended something like:
void do_something(my_type void_x)
{
struct _my_type *x = void_x;
printf("Value: %d\n", x->a);
}
This is now syntactically correct (I think; I haven't actually run it past a compiler). You have not shown how it is used; indeed, since the user code has no way to generate a pointer to a valid structure, there is no way for this code to be used safely.
Your test code (unshown — why don't you show your test code) might look something like this:
#include "api.h"
int main(void)
{
my_type x = 0;
do_something(x);
return 0;
}
Alternatively, it might not have the = 0 initializer in place. Either way, your code is unable to function sanely, and a core dump is almost inevitable. When you hide the structure from the user, you have to provide them with a mechanism to get hold of a valid (pointer to) the structure, and you've not done that.
Version 1
This is a better way to do it, because it is more nearly type-safe:
api.h version 1
typedef struct _my_type *my_type;
void do_something(my_type x);
core.c version 1
#include "api.h"
struct _my_type
{
int a;
};
Note the added semi-colon, and the include of the api.h file.
void do_something(my_type x)
{
// Now you don't have to do casting here!
//struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Version 2
Actually, we can debate the wisdom of hiding the pointer; I would prefer not to do so:
api.h version 2
#ifndef API_H_INCLUDED
#define API_H_INCLUDED
typedef struct my_type my_type;
extern void do_something(my_type *x);
extern my_type *my_type_initializer(void);
extern void my_type_release(my_type *x);
#endif /* API_H_INCLUDED */
core.c version 2
#include "api.h"
#include <stdio.h>
#include <stdlib.h>
struct my_type
{
int a;
};
void do_something(my_type *x)
{
printf("Value: %d\n", x->a);
}
my_type *my_type_initializer(void)
{
my_type *x = malloc(sizeof(*x));
x->a = 57; // More plausibly, this would be 0
return x;
}
void my_type_release(my_type *x)
{
free(x);
}
main.c
#include "api.h"
int main(void)
{
my_type *x = my_type_initializer();
do_something(x);
my_type_release(x);
return 0;
}
That's nice and clean. Of course, the user cannot allocate a struct my_type (only a pointer to it), so you need a function to allocate the structure for them. Think of the Standard C Library, and the FILE type, and fopen() to allocate and fclose() to release and fprintf() etc to manipulate the type. The my_type_initializer() is functioning as an analogue to fopen(), my_type_release() as an analogue to fclose(), and do_something() as an analogue to fprintf().
Jonathan, you beat me to an answer, but this may be helpful as well. Here, api.c contains the (private) implementation, and api.h provides the interface to be consumed by other code such as main.c.
// main.c: uses only the public interface to the private code
#include "api.h"
int main(int argc, char *argv[]) {
void *foo;
foo = create_foo("five", 5);
print_foo(foo);
delete_foo(foo);
}
// EOF main.c
// api.h: the public interface
#ifndef _api_h_
#define _api_h_
void *create_foo(char *name, int number);
void print_foo(void *foo);
void delete_foo(void *foo);
#endif // _api_h_
// api.c: the private implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// The real structure is private to the implementation.
typedef struct {
char name[20];
int number;
} real_struct;
// Create a new structure, initialize, return as ptr-to-void.
void *create_foo(char *name, int number) {
real_struct *s = malloc(sizeof(real_struct));
strcpy(s->name, name);
s->number = number;
return (void *) s;
}
// Print the data.
void print_foo(void *foo) {
real_struct *s = (real_struct *) foo;
printf("name: %s, number: %d\n", s->name, s->number);
}
// Release the memory.
void delete_foo(void *foo) {
free(foo);
}
// EOF api.c
This code should compile and run:
$ gcc -o foo main.c api.c
$ ./foo
name: five, number: 5