I want to create a constructor using C.
What is the cleanest way to achieve this?
My attempt:
#include <stdio.h>
struct line {
void (*add_line_ptr)(struct line*, int x, int y);
int x;
int y;
};
void add_line(struct line* lptr, int x, int y)
{
lptr->x = x;
lptr->y = y;
}
int main()
{
struct line line1 = {add_line, 0, 0};
line1.add_line_ptr(&line1, 10, 20);
printf("%d %d\n", line1.x, line1.y);
}
I think that using line1.add_line(&line1, is a bit redundant - since it's quite obvious that I want to do the operation on line1.
Is there a way to implement this without passing a pointer to the "object"(struct)? or some other way I didn't think of?
Using function pointers just for the sake of emulating C++-like syntax is just messy with no obvious benefits. You won't have RAII in C no matter what you do, so you need to call constructors/destructors explicitly. If you do so by typing obj.foo() or obj = foo() has absolutely nothing to do with OO, it's mere coding style.
The main problem here though, is that your code does not have proper OO design, since the struct is completely open and not using private encapsulation. For the same reason as class line { public: int x; int y; }; is not proper OO either - you don't get OO just because you smash some related variables into an aggregate type, regardless of language.
"Cleanest"/"prettiest" would mean full private encapsulation. In C, that can be achieved with opaque types. I prefer to implement them without hiding pointers behind typedef, so:
line.h
#include <stdio.h>
#include <stdlib.h>
typedef struct line line; // forward declaration of incomplete type
line* line_construct (int x, int y);
line.c
#include "line.h"
struct line { // actual definition of the struct, local to line.c
int x; // private variable
int y; // private variable
};
line* line_construct (int x, int y)
{
line* obj = malloc (sizeof *obj);
if(obj == NULL) { /* error handling here */ }
obj->x = x;
obj->y = y;
return obj;
}
caller.c
#include "line.h"
int main(void)
{
line* x = line_construct(10, 20);
}
Here line is 100% encapsulated and the contents of the struct cannot be accessed by the caller. Since I don't hide pointers behind typedef, the caller must always use line* pointers and can never declare an instance of the object directly.
If the constructor is only meant to zero-out the struct members, then it doesn't need to get passed any parameters but can do so internally.
And obviously you need to implement a corresponding destructor with free as well.
line* line_destruct(line* obj) { free(obj); return NULL; } or so.
I wouldn't put the initializer into your structure to begin with. Other functions, sure, but not the first one. Something like this:
#include <stdio.h>
struct line {
int x;
int y;
};
void add_line(struct line *lptr, int x, int y)
{
lptr->x = x;
lptr->y = y;
}
int main()
{
struct line line1 = {0, 0};
add_line(&line1, 10, 20);
printf("%d %d\n", line1.x, line1.y);
}
The reason is that you have to assign the initializer anyway after you allocate your structure, either implicitly or explicitly. In OOP languages you normally name the class you want once, and both the allocator and initializer will run. In C you have to run them separately. Whether you allocate an object on the stack or on the heap, you will have to explicitly name the function you want to call at least once anyway.
Related
I wanted to create a function for my struct. I searched on the internet and found this two helpful links:
Can I define a function inside a C structure?
Define functions in structs
Most of the answers defined this:
typedef struct Point
{
int x;
int y;
void (*Print)(Point* p);
} Point;
Meaning that if you wanted to call the Print function on a struct you will have to pass the same point again. In other words you would do something like this:
somePoint.Print(&somePoint);
That works but it will be better if you don't have to pass &somePoint as an argument. In other words my goal is to achieve the same behavior by calling somePoint.Print(); instead of somePoint.Print(&somePoint); .
Anyways I am no expert in C and I was about to post this answer on those links:
#include <stdlib.h>
#include <string.h>
typedef struct Point
{
int x;
int y;
void (*Print)();
} Point;
void _print_point(Point* p)
{
printf("x=%d,y=%d\n", p->x, p->y);
}
void Point_Constructor(Point* p, int x, int y){
p->x = x;
p->y = y;
// create wrapper function
void inline_helper() { _print_point(p);}
p->Print = inline_helper;
}
int main(){
Point p1;
Point_Constructor(&p1,1,2);
p1.Print(); // I CAN CALL THE PRINT FUNCTION WITHOUT HAVING TO PASS AGAIN THE SAME POINT AS REFERENCE
return 0;
}
Why nobody suggested that? Is it safe if I run code like that?
I have the following in C (not C++!):
module.c
struct Private {...};
void foo(void* private, int param) {...}
module.h
#define PRIVATE_SIZE ???;
void foo(void* private, int param);
main.c
char m1[PRIVATE_SIZE];
char m2[PRIVATE_SIZE];
int main()
{
foo(m1, 10);
foo(m2, 20);
}
How can I expose sizeof(Private) at compile time so that application can statically allocate its storage without exposing Private type?
Note, this is a very limited embedded system and dynamic allocation is not available.
You shouldn't expose the size of the struct to the caller, because that breaks the whole purpose of having private encapsulation in the first place. Allocation of your private data is no business of the caller. Also, avoid using void* because they complete lack type safety.
This is how you write private encapsulation in C:
In module.h, forward declare an incomplete type typedef struct module module;.
In module.c, place the struct definition of this struct. it will only be visible to module.c and not to the caller. This is known as opaque types.
The caller can only allocate pointers to this struct, never allocate objects.
Caller code might look like:
#include "module.h"
...
module* m;
result = module_init(&m)
And the module_init function acts as a "constructor", declared in module.h and defined in module.c:
bool module_init (module** obj)
{
module* m = malloc(sizeof *m);
...
m->something = ...; // init private variables if applicable
*obj = m;
return true;
}
If the caller does need to know the size of the objects, it would only be for the purpose of hard copy etc. If there's a need for that, provide a copy function which encapsulates the allocation and copy ("copy constructor"), for example:
result module_copy (module** dst, const module* src);
Edit:
Please note that the manner of allocation is a separate issue. You don't have to use dynamic allocation for the above design. In embedded systems for example, it is common to use static memory pools instead. See Static allocation of opaque data types
You can't allocate size for a struct such as this because it isn't known at compile time. Even if you did know the size at run time, you'd still have issues due to alignment.
There is a possible solution which involves defining a separate structure that has the same size and alignment requirements as the private struct.
For example:
module.h:
#include <inttypes.h>
struct Public {
uint64_t opaque1;
uint64_t opaque2;
uint64_t opaque3;
};
void init(struct Public *p);
module.c:
#include <assert.h>
#include <stdalign.h>
#include "module.h"
struct Private {
int a;
double b;
float c;
};
static_assert(sizeof(struct Private)==sizeof(struct Public), "sizes differ");
static_assert(alignof(struct Private)==alignof(struct Public), "alignments differ");
void init(struct Public *p)
{
struct Private *pr = (struct Private *)p;
pr->a = 2;
pr->b = 2.5;
pr->c = 2.4f;
}
The Public and Private structs are guaranteed to have the same size, and the alignment should be the same. There is the possibility of the user writing the the "opaque" fields of the public struct, in which case you could have aliasing issues regarding effective types, but if the user can be trusted to do that then this should work.
Another, more robust option, is if you have some idea of the maximum number of objects you want to support. If that's the case, you can have a static array of these objects in your implementation file, and the init function would return a pointer to one of the objects in this list. Then you'd have a related cleanup function that would free the instance.
For example:
module.c:
struct Private {
int a;
double b;
float c;
};
struct PrivateAllocator {
struct Private obj;
int used;
};
struct PrivateAllocator list[5] = {
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 }
};
struct Private *private_init()
{
int i;
for (i=0; i<5; i++) {
if (!list[i].used) {
list[i].used = 1;
return &list[i].obj;
}
}
return NULL;
}
void private_free(struct Private *p)
{
int i;
for (i=0; i<5; i++) {
if (&list[i].obj == p) {
list[i].used = 0;
return;
}
}
}
In conforming C code you can't create a static instance of an arbitrary unknown type even if you know its size at compile time (not even if you know the alignment).
Let's say you try doing it anyway. How would you do it, given the size in a macro or enum PRIVATE_SIZE?
unsigned char obj[PRIVATE_SIZE];
And then you'd pass (void*)obj to wherever its needed, right?
Well, this breaks the aliasing rules. While you can legally access any individual char/byte in any object, you can't do it the other way around saying that those chars are not chars, they are just storage behind other types. That is, you can't legally have a short int superimposed on top of, say, obj[2] and obj[3] through smarty-pants casts (e.g. ((struct Private*)obj)->my_short = 2;). The only legal way to do something like this would be through memcpy(), e.g. memcpy(&temp, obj, sizeof temp); and then back after the modification. Or you'd need to work with individual chars of obj[].
There are two possible ways to sort of do it. One is described in another answer, basically define the instance where the type is known, but only let the outside world have a pointer to it.
Another, very similar, define it in assembly code and, again, let the outside world have a pointer to it. The "beauty" of the assembly way is that you really only need a name, an alignment and a size to allocate space for a named object.
And if you put the instances into a special data section (see the gcc's section attribute and the linker scripts), you may even have all of the instances in the same place (think, array) and even find out their cumulative size and therefore count.
Yet another thing to do while not explicitly violating any C rules is to still use this unsigned char obj[PRIVATE_SIZE] trick, but launder it by passing it unchanged through an assembly function that the C compiler can't look into, e.g. something like
// struct Private* launder(unsigned char*);
.text
.globl launder
launder:
move %first_param_reg, %return_reg
ret
But you'll really need to change unsigned char obj[PRIVATE_SIZE] to something that would have proper alignment on your architecture, e.g. double obj[PRIVATE_SIZE / sizeof(double)] (or the same with long long if you like that way better).
As for PRIVATE_SIZE, you can have a check at compile time that it matches the size of the type, e.g.
#include "mod.h" // mod.h defines PRIVATE_SIZE
struct Private { ... };
extern char StAtIcAsSeRt[sizeof(struct Private) == PRIVATE_SIZE];
How to expose C struct size without exposing its type?
If able to compromise a bit: (statically --> main() local)
with variable length arrays (C99), use a helper function and put the array in main().
module.h
size_t foo_size(void);
main.c
int main() {
char m1[foo_size()];
foo(m1, 10);
}
Additional work needed to account for alignment issues.
Consider relaxing your goal as suggested.
C99 allowes you to use variable length array.
private.h:
#include <stdio.h>
extern const size_t size;
private.c:
#include "private.h"
struct Private {
int x;
int y;
int z;
};
const size_t size = sizeof(struct Private);
main.c:
#include <stdio.h>
#include "private.h"
int main(void) {
char m1[size]; //variable length array
printf("Size of m1 = %ld\n", sizeof(m1));
}
In an attempt to encapsulate struct members (in a similar way as discussed in this question), I created the code below.
In the code below, I have a c-struct, which contains methods to access members of the struct which are hidden (by being cast into a struct otherwise the same but without the hidden properties)
#include <stdio.h>
typedef struct class {
int publicValue;
int (*getPV)();
void (*setPV)(int newPV);
} class;
typedef struct classSource {
int publicValue;
int apv;
int (*getPV)();
void (*setPV)(int newPV);
int PV;
} classSource;
class class_init() {
classSource cs;
cs.publicValue = 15;
cs.PV = 8;
int class_getPV() {
return cs.PV;
};
void class_setPV(int x) {
cs.PV = x;
};
cs.getPV = class_getPV;
cs.setPV = class_setPV;
class *c = (class*)(&cs);
return *c;
}
int main(int argc, const char * argv[]) {
class c = class_init();
c.setPV(3452);
printf("%d", c.publicValue);
printf("%d", c.getPV());
return 0;
}
When I run this, I get a segmentation fault error. However, I noticed that if I comment out certain lines of code, it (seems) to work okay:
#include <stdio.h>
typedef struct class {
int publicValue;
int (*getPV)();
void (*setPV)(int newPV);
} class;
typedef struct classSource {
int publicValue;
int apv;
int (*getPV)();
void (*setPV)(int newPV);
int PV;
} classSource;
class class_init() {
classSource cs;
cs.publicValue = 15;
cs.PV = 8;
int class_getPV() {
return cs.PV;
};
void class_setPV(int x) {
cs.PV = x;
};
cs.getPV = class_getPV;
cs.setPV = class_setPV;
class *c = (class*)(&cs);
return *c;
}
int main(int argc, const char * argv[]) {
class c = class_init();
c.setPV(3452);
//printf("%d", c.publicValue);
printf("%d", c.getPV());
return 0;
}
I presume that it might have something to do with using the initializer to add the getter and setter methods to the struct, as those might overwrite memory.
Is what I am doing undefined behavior? Is there a way to fix this?
EDIT: With the help of the answer below, I have re-written the code. In case anyone wants to see the implementation, below is the revised code
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int pub;
} class;
typedef struct {
class public;
int PV;
} classSource;
int class_getPV(class *c) {
return ((classSource*)c)->PV;
}
void class_setPV(class *c, int newPV) {
((classSource*)c)->PV = newPV;
}
class *class_init() {
classSource *cs = malloc(sizeof(*cs));
if((void*)cs == (void*)NULL) {
printf("Error: malloc failed to allocate memory");
exit(1);
}
cs->public.pub = 10;
cs->PV = 8;
return &(cs->public);
}
int main() {
class *c = class_init();
class_setPV(c,4524);
printf("%d\n",class_getPV(c));
printf("%d\n",c->pub);
free(c);
return 0;
}
There are at least three separate problems in your code.
You don't actually have a "struct otherwise the same but without the hidden properties". Your class and classSource structs have their getPV and setPV members in different places. Internally member access boils down to byte offsets from the beginning of the struct. To have a fighting chance of working, your code would need to have a common initial prefix of members between the two struct types (i.e. get rid of int apv; or move it to the end).
You're returning a struct by value, which automatically makes a copy. You've reimplemented the object slicing problem: Because the return value has type class, only the members of class will be copied. The extra members of classSource have been "sliced off".
You're using nested functions. This is not a standard feature of C; GCC implements it as an extension and says:
If you try to call the nested function through its address after the containing function exits, all hell breaks loose.
This is exactly what's happening in your code: You're calling c.setPV(3452); and c.getPV after class_init has returned.
If you want to fix these problems, you'd have to:
Fix your struct definitions. At minimum all members of class need to appear at the beginning of classSource in the same order. Even if you do that, I'm not sure you wouldn't still run into undefined behavior (e.g. you might be violating an aliasing rule).
I'm somewhat sure that embedding one struct in the other would be OK, however:
typedef struct classSource {
class public;
int PV;
} classSource;
Now you can return &cs->public from your initializer, and your methods can cast the class * pointer back to classSource *. (I think this is OK because all struct pointers have the same size/representation, and X.public as the first member is guaranteed to have the same memory address as X.)
Change your code to use pointers instead. Returning a pointer to a struct avoids the slicing problem, but now you have to take care of memory management (malloc the struct and take care to free it later).
Don't use nested functions. Instead pass a pointer to the object to each method:
class *c = class_init();
c->setPV(c, 3452);
int x = c->getPV(c);
This is somewhat tedious, but this is what e.g. C++ does under the hood, essentially. Except C++ doesn't put function pointers in the objects themselves; there's no reason to when you can either use normal functions:
setPV(c, 3452);
int x = getPV(c);
... or use a separate (global, constant, singleton) struct that just stores pointers to methods (and no data). Each object then only contains a pointer to this struct of methods (this is known as a vtable):
struct classInterface {
void (*setPV)(class *, int);
int (*getPV)(const class *);
};
static const classInterface classSourceVtable = {
class_setPV, // these are normal functions, defined elsewhere
class_getPV
};
Method calls would look like this:
c->vtable->setPV(c, 1234);
int x = c->vtable->getPV(c);
But this is mainly useful if you have several different struct types that share a common public interface (class) and you want to write code that works uniformly on all of them.
Can we have functions in structures in C language?
Could someone please give an example of how to implement it and explain?
No, structures contain data only. However, you can define a pointer to a function inside of a struct as below:
struct myStruct {
int x;
void (*anotherFunction)(struct foo *);
}
The answer is no, but there is away to get the same effect.
Functions can only be found at the outermost level of a C program. This improves run-time speed by reducing the housekeeping associated with function calls.
As such, you cannot have a function inside of a struct (or inside of another function) but it is very common to have function pointers inside structures. For example:
#include <stdio.h>
int get_int_global (void)
{
return 10;
}
double get_double_global (void)
{
return 3.14;
}
struct test {
int a;
double b;
};
struct test_func {
int (*get_int) (void);
double (*get_double)(void);
};
int main (void)
{
struct test_func t1 = {get_int_global, get_double_global};
struct test t2 = {10, 3.14};
printf("Using function pointers: %d, %f\n", t1.get_int(), t1.get_double());
printf("Using built-in types: %d, %f\n", t2.a, t2.b);
return 0;
}
A lot of people will also use a naming convention for function pointers inside structures and will typedef their function pointers. For example you could declare the structure containing pointers like this:
typedef int (*get_int_fptr) (void);
typedef double (*get_double_fptr)(void);
struct test_func {
get_int_fptr get_int;
get_double_fptr get_double;
};
Everything else in the code above will work as it is. Now, get_int_fptr is a special type for a function returning int and if you assume that *_fptr are all function pointers then you can find what the function signature is by simply looking at the typedef.
No, it has to be implemented like this :
typedef struct S_House {
char* name;
int opened;
} House;
void openHouse(House* theHouse);
void openHouse(House* theHouse) {
theHouse->opened = 1;
}
int main() {
House myHouse;
openHouse(&myHouse);
return 0;
}
I have some code with multiple functions very similar to each other to look up an item in a list based on the contents of one field in a structure. The only difference between the functions is the type of the structure that the look up is occurring in. If I could pass in the type, I could remove all the code duplication.
I also noticed that there is some mutex locking happening in these functions as well, so I think I might leave them alone...
If you ensure that the field is placed in the same place in each such structure, you can simply cast a pointer to get at the field. This technique is used in lots of low level system libraries e.g. BSD sockets.
struct person {
int index;
};
struct clown {
int index;
char *hat;
};
/* we're not going to define a firetruck here */
struct firetruck;
struct fireman {
int index;
struct firetruck *truck;
};
int getindexof(struct person *who)
{
return who->index;
}
int main(int argc, char *argv[])
{
struct fireman sam;
/* somehow sam gets initialised */
sam.index = 5;
int index = getindexof((struct person *) &sam);
printf("Sam's index is %d\n", index);
return 0;
}
You lose type safety by doing this, but it's a valuable technique.
[ I have now actually tested the above code and fixed the various minor errors. It's much easier when you have a compiler. ]
Since structures are nothing more than predefined blocks of memory, you can do this. You could pass a void * to the structure, and an integer or something to define the type.
From there, the safest thing to do would be to recast the void * into a pointer of the appropriate type before accessing the data.
You'll need to be very, very careful, as you lose type-safety when you cast to a void * and you can likely end up with a difficult to debug runtime error when doing something like this.
I think you should look at the C standard functions qsort() and bsearch() for inspiration. These are general purpose code to sort arrays and to search for data in a pre-sorted array. They work on any type of data structure - but you pass them a pointer to a helper function that does the comparisons. The helper function knows the details of the structure, and therefore does the comparison correctly.
In fact, since you are wanting to do searches, it may be that all you need is bsearch(), though if you are building the data structures on the fly, you may decide you need a different structure than a sorted list. (You can use sorted lists -- it just tends to slow things down compared with, say, a heap. However, you'd need a general heap_search() function, and a heap_insert() function, to do the job properly, and such functions are not standardized in C. Searching the web shows such functions exist - not by that name; just do not try "c heap search" since it is assumed you meant "cheap search" and you get tons of junk!)
If the ID field you test is part of a common initial sequence of fields shared by all the structs, then using a union guarantees that the access will work:
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int id;
long junk2;
} Bar;
typedef union
{
struct
{
int id;
} common;
Foo foo;
Bar bar;
} U;
int matches(const U *candidate, int wanted)
{
return candidate->common.id == wanted;
}
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 42, 0 };
U fu;
U bu;
fu.foo = f;
bu.bar = b;
puts(matches(&fu, 23) ? "true" : "false");
puts(matches(&bu, 42) ? "true" : "false");
return 0;
}
If you're unlucky, and the field appears at different offsets in the various structs, you can add an offset parameter to your function. Then, offsetof and a wrapper macro simulate what the OP asked for - passing the type of struct at the call site:
#include <stddef.h>
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int junk2;
int id;
} Bar;
int matches(const void* candidate, size_t idOffset, int wanted)
{
return *(int*)((const unsigned char*)candidate + idOffset) == wanted;
}
#define MATCHES(type, candidate, wanted) matches(candidate, offsetof(type, id), wanted)
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 0, 42 };
puts(MATCHES(Foo, &f, 23) ? "true" : "false");
puts(MATCHES(Bar, &b, 42) ? "true" : "false");
return 0;
}
One way to do this is to have a type field as the first byte of the structure. Your receiving function looks at this byte and then casts the pointer to the correct type based on what it discovers. Another approach is to pass the type information as a separate parameter to each function that needs it.
You can do this with a parameterized macro but most coding policies will frown on that.
#include
#define getfield(s, name) ((s).name)
typedef struct{
int x;
}Bob;
typedef struct{
int y;
}Fred;
int main(int argc, char**argv){
Bob b;
b.x=6;
Fred f;
f.y=7;
printf("%d, %d\n", getfield(b, x), getfield(f, y));
}
Short answer: no. You can, however, create your own method for doing so, i.e. providing a specification for how to create such a struct. However, it's generally not necessary and is not worth the effort; just pass by reference. (callFuncWithInputThenOutput(input, &struct.output);)
I'm a little rusty on c, but try using a void* pointer as the variable type in the function parameter. Then pass the address of the structure to the function, and then use it he way that you would.
void foo(void* obj);
void main()
{
struct bla obj;
...
foo(&obj);
...
}
void foo(void* obj)
{
printf(obj -> x, "%s")
}