Accessing a general structure member using a variable - c

Not entirely sure my question title describes what I want to do, but couldn't think how better to word it!! I'm using C, and perhaps the pseudocode below will describe what I'm trying to do:
typedef struct obj
{
char *str1;
char *str2;
char *str3;
} object;
/* global variable */
object *glob;
void black_box_function(local, member) ????
{
/* Do something with glob->member and local->member */
}
void main()
{
object *ob1, *ob2;
/* Initialise glob, ob1 and ob2 somewhere */
black_box_function(ob1, str1);
black_box_function(ob2, str3);
}
Hopefully, you can see what I'm trying to do. I have a "black-box" function that will do something with a particular member, and I need to be able to tell the black-box function which member to use.
I don't want to just pass the member directly to the function, like in this code, as that won't fit into the rest of my code easily.
black_box_function(ob1->member, glob->member)

You could do the following magic (with GCC extensions):
#define black_box(local, member) black_box_function((local), __builtin_offsetof(object, member))
void black_box_function(object *local, int offset)
{
char *lmember = ((void *)local) + offset;
char *gmember = ((void *)global) + offset;
/* do stuff */
}
However, you must know in advance the type of your members. Keep in mind that C is not a dynamically typed language, so you have no runtime introspection at all.
EDIT: You can implement offsetof() functionality without resorting to GCC extensions, like this:
#define offsetof(type, field) ((int) (unsigned long) &((type *) 0)->field)

Perhaps you could create accessor functions for your struct and pass those accessors as function pointer arguments instead of passing the members directly
typedef struct
{
int a;
int b;
} foo;
typedef int* (*accessor)(foo*);
int* get_a(foo* f) { return &f->a; }
int* get_b(foo* f) { return &f->b; }
void black_box_function(foo* object, accessor fn)
{
int* p = fn(object);
}
int main(void)
{
foo bar1;
foo bar2;
black_box_function(&bar1, get_a);
black_box_function(&bar2, get_b);
return 0;
}

Since all are char*, you can redefine the struct like:
typedef struct obj
{
char **str; // Array of c
} object;
Then you can send the index of str from main which you want work with:
black_box_function(obj1, index)
So you can it like obj1->str[i] in your blackbox.
Btw, black-box_function will not compile.
On a side note: A little more info/code on your blackbox function and compilable code would give a better picture of what you are trying to do.

Related

Using a function from a function array stored in a struct in C

I declared a struct like this one :
typedef struct s_data {
char buff[2048];
int len;
void *func[10];
struct data *next;
} t_data;
In my code, when passing a *data, I assigned some functions (just giving one so it is more understandable)
void init_data(t_data *data)
{
data->len = 0;
data->func[0] = &myfirstfunctions;
//doing the same for 9 others
}
My first function would be something taking as argument *data, and an int.
Then, I try to use this function in another function, doing
data->func[0](data, var);
I tried this and a couple of other syntaxes involving trying to adress (*func[0]) but none of them work. I kind of understood from other much more complex questions over there that I shouldn't store my function like this, or should cast it in another typedef, but I did not really understand everything as I am kind of new in programming.
void* can only be used reliably as a generic object pointer ("pointer to variables"). Not as a generic function pointer.
You can however convert between different function pointer types safely, as long as you only call the actual function with the correct type. So it is possible to do just use any function pointer type as the generic one, like this:
void (*func[10])(void);
...
func[0] = ((void)(*)(void))&myfirstfunction;
...
((whatever)func[0]) (arguments); // call the function
As you might note, the function pointer syntax in C is horrible. So I'd recommend using typedefs:
typedef void genfunc_t (void);
typedef int somefunc_t (whatever*); // assuming this is the type of myfirstfunction
Then the code turns far easier to read and write:
genfunc_t* func [10];
...
func[0] = (genfunc_t*)&myfirstfunction;
...
((somefunc_t*)func[0]) (arguments);
If all of your functions will have the same signature, you can do this like:
#include <stdio.h>
typedef void (*func)(void *, int);
struct s_data {
char buff[2048];
int len;
func f[10];
struct s_data *next;
};
static void
my_first_function(void *d, int x)
{
(void)d;
printf("%d\n", x + 2);
}
static void
init_data(struct s_data *data)
{
data->len = 1;
data->f[0] = my_first_function;
}
int
main(void)
{
struct s_data d;
init_data(&d);
d.f[0](NULL, 5);
return 0;
}
If your functions have different signatures, you will want to either use a union, or perhaps you will need several different members of the struct to store the function pointers.
The problem is that you haven't actually declared an array of function pointers. What you actually did is an array of pointers to void.
The syntax of declaring a pointer to function is as following:
function_return_type (*pointer_name)(arg1_type,arg2_type,...);
Then you can create an array of pointers to functions:
function_return_type (*arr_name[])(arg1_type, arg2_type,...)
Therefore, the declaration of your structure should look like this:
typedef void (*pointer_to_function)(void *, int);
struct s_data {
char buff[2048];
int len;
pointer_to_function array_of_pointeters[10];
struct s_data *next;
};
Good luck:)

Anonymous functions return dynamically allocated values

The question is based on a design pattern solution easily doable in other languages but difficult to implement in C. The narrowed down code is below.
Building on this answer, I'm trying to find a solution for the dynamically generated values in an anonymous function.
Excerpt from the answer:
int (*max)(int, int) =
({
int __fn__ (int x, int y) { return x > y ? x : y; }
__fn__;
});
Static Library Code
struct Super{
}
void add(struct Super *(*superRef)()) {
// cache the reference (in some linked list)
// later at some point when an event occurs.
struct Super *super = superRef(); // instantiate and use it.
}
Client Code linked: User of the Library Code
struct Sub{
struct Super *super;
}
add(({
struct Sub __fn__() { return malloc(sizeof(struct Sub)); } // error
__fn__;
}));
Error:
error: passing 'void' to parameter of incompatible type 'struct Sub *(*)()
As per the request for clarification, think of the receiving function in a static library file receiving references to the structure objects (non-instantiated). The lib receives this object from the client code.
Secondly the client or static library library doesn't instantiate the received structure reference right away. Later when there's a notification in the system, the structure reference is called to instantiate and execute the rest of the stuff.
I repeat, the specific requirement is to hold non-instantiated references to the structures passed by users of the library (client code).
Summary
Basically a Runner that receives pointer to a polymorphic factory method which it caches and later calls to instantiate and executes when an event occurs.
The correct order is:
learn C
do magic
It just will not work in the other way. ({}) does not bend the semantics for you. If your add expects a function which returns struct Super*, it will not work with struct Sub, not even if you put the missing * there.
This just works on TutorialsPoint:
#include <stdio.h>
#include <stdlib.h>
int max(int a,int b){
if(a>b)
return a;
return b;
}
struct Super{};
void add(struct Super *(*superRef)()) {
struct Super *(*secretStorage)()=superRef;
/* ... */
struct Super *super = secretStorage();
/* ... */
free(super);
printf("Stillalive\n");
}
int main()
{
printf("Hello, World!\n");
int (*myMax)(int,int); // <-- that is a function pointer
myMax=max; // <-- set with oldschool function
printf("%d\n",myMax(1,2));
myMax = ({ // <-- set with fancy magic
int __fn__ (int x, int y) { return x < y ? x : y; }
__fn__;
});
printf("%d - intentionally wrong\n",myMax(1,2));
add(
({
struct Super* fn(){
printf("Iamhere\n");
return malloc(sizeof(struct Super));
}
fn;}));
printf("Byfornow\n");
return 0;
}
Created a small library project with anonymous magic embedded in anonymous magic and heap allocation. It does not make much sense, but it works:
testlib.h
#ifndef TESTLIB_H_
#define TESTLIB_H_
struct Testruct{
const char *message;
void (*printmessage)(const char *message);
};
extern struct Testruct *(*nonsense())();
#endif
testlib.c
#include "testlib.h"
#include <stdio.h>
#include <stdlib.h>
const char *HELLO="Hello World\n";
struct Testruct *(*nonsense())(){
return ({
struct Testruct *magic(){
struct Testruct *retval=malloc(sizeof(struct Testruct));
retval->message=HELLO;
retval->printmessage=({
void magic(const char *message){
printf(message);
}
magic;
});
return retval;
}
magic;
});
}
test.c
#include "testlib.h"
#include <stdio.h>
#include <stdlib.h>
int main(){
struct Testruct *(*factory)()=nonsense();
printf("Alive\n");
struct Testruct *stuff=factory();
printf("Alive\n");
stuff->printmessage(stuff->message);
printf("Alive\n");
free(stuff);
printf("Alive\n");
return 0;
}
I followed the steps in https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html for building an running it (practically 3 gcc calls: gcc -c -Wall -Werror -fpic testlib.c, gcc -shared -o libtestlib.so testlib.o, gcc -L. -Wall -o test test.c -ltestlib and a bit of fight with LD_LIBRARY_PATH)
The code shown in the question is not standard C, but the GNU C variant that GCC supports. Unfortunately, there does not seem to be a gnu-c tag, to correctly specify the variant of C involved.
Furthermore, the use case seems to rely on shoehorning specific type of object-oriented paradigm into a C library interface. This is horrible, because it involves assumptions and features C simply does not have. There is a reason why C (and GNU-C) and C++ and Objective-C are different programming languages.
The simple answer to "functions returning dynamically allocated values" where the type of the value is opaque to the library, is to use void *, and for function pointers, (void *)(). Note that in POSIX C, void * can also hold a function pointer.
The more complex answer would describe how libraries like GObject support object-oriented paradigms in C.
In practice, especially in POSIX C, using a type tag (usually int, but can be any other type) and an union, one can implement polymorphic structures, based on an union of structures with all having that type tag as the same first element. The most common example of such functionality is struct sockaddr.
Basically, your header file defines one or more structures with the same initial member, for example
enum {
MYOBJECT_TYPE_DOUBLE,
MYOBJECT_TYPE_VOID_FUNCTION,
};
struct myobject_double {
int type; /* MYOBJECT_TYPE_DOUBLE */
double value;
};
struct myobject_void_function {
int type; /* MYOBJECT_TYPE_VOID_FUNCTION */
void (*value)();
};
and at the end, an union type, or a structure type with an anonymous union (as provided by C11 or GNU-C), of all the structure types,
struct myobject {
union {
struct { int type; }; /* for direct 'type' member access */
struct myobject_double as_double;
struct myobject_void_function as_void_function;
};
};
Note that technically, wherever that union is visible, it is valid to cast any pointer of any of those structure types to another of those structure types, and access the type member (see C11 6.5.2.3p6). It is not necessary to use the union at all, it suffices for the union to be defined and visible.
Still, for ease of maintenance (and to avoid arguments with language lawyer wannabes who did not read that paragraph in the C standard), I do recommend using the structure containing the anonymous union as the "base" type in the library interface.
For example, the library might provide a function to return the actual size of some object:
size_t myobject_size(struct myobject *obj)
{
if (obj)
switch (obj->type) {
case MYOBJECT_TYPE_DOUBLE: return sizeof (struct myobject_double);
case MYOBJECT_TYPE_VOID_FUNCTION: return sizeof (struct myobject_void_function);
}
errno = EINVAL;
return 0;
}
It seems to me OP is trying to implement a factory pattern, where the library function provides the specification (class in OOP) for the object created, and a method to produce those objects later.
The only way in C to implement dynamic typing is via the kind of polymorphism I show above. This means that the specification for the future objects (again, class in OOP) must be an ordinary object itself.
The factory pattern itself is pretty easy to implement in standard C. The library header file contains for example
#include <stdlib.h>
/*
* Generic, application-visible stuff
*/
struct any_factory {
/* Function to create an object */
void *(*produce)(struct any_factory *);
/* Function to discard this factory */
void (*retire)(struct any_factory *);
/* Flexible array member; the actual
size of this structure varies. */
unsigned long payload[];
};
static inline void *factory_produce(struct any_factory *factory)
{
if (factory && factory->produce)
return factory->produce(factory);
/* C has no exceptions, but does have thread-local 'errno'.
The error codes do vary from system to system. */
errno = EINVAL;
return NULL;
}
static inline void factory_retire(struct any_factory *factory)
{
if (factory) {
if (factory->retire) {
factory->retire(factory);
} else {
/* Optional: Poison function pointers, to easily
detect use-after-free bugs. */
factory->produce = NULL;
factory->retire = NULL; /* Already NULL, too. */
/* Free the factory object. */
free(factory);
}
}
}
/*
* Library function.
*
* This one takes a pointer and size in chars, and returns
* a factory object that produces dynamically allocated
* copies of the data.
*/
struct any_factory *mem_factory(const void *, const size_t);
where factory_produce() is a helper function which invokes the factory to produce one object, and factory_retire() retires (discards/frees) the factory itself. Aside from the extra error checking, factory_produce(factory) is equivalent to (factory)->produce(factory), and factory_retire(factory) to (factory)->retire(factory).
The mem_factory(ptr, len) function is an example of a factory function provided by a library. It creates a factory, that produces dynamically allocated copies of the data seen at the time of the mem_factory() call.
The library implementation itself would be something along the lines of
#include <stdlib.h>
#include <string.h>
#include <errno.h>
struct mem_factory {
void *(*produce)(struct any_factory *);
void (*retire)(struct any_factory *);
size_t size;
unsigned char data[];
};
/* The visibility of this union ensures the initial sequences
in the structures are compatible; see C11 6.5.2.3p6.
Essentially, this causes the casts between these structure
types, for accessing their initial common members, valid. */
union factory_union {
struct any_factory any;
struct mem_factory mem;
};
static void *mem_producer(struct any_factory *any)
{
if (any) {
struct mem_factory *mem = (struct mem_factory *)any;
/* We return a dynamically allocated copy of the data,
padded with 8 to 15 zeros.. for no reason. */
const size_t size = (mem->size | 7) + 9;
char *result;
result = malloc(size);
if (!result) {
errno = ENOMEM;
return NULL;
}
/* Clear the padding. */
memset(result + size - 16, 0, 16);
/* Copy the data, if any. */
if (mem->size)
memcpy(result, mem->data, size);
/* Done. */
return result;
}
errno = EINVAL;
return NULL;
}
static void mem_retirer(struct any_factory *any)
{
if (any) {
struct mem_factory *mem = (struct mem_factory *)any;
mem->produce = NULL;
mem->retire = NULL;
mem->size = 0;
free(mem);
}
}
/* The only exported function:
*/
struct any_factory *mem_factory(const void *src, const size_t len)
{
struct mem_factory *mem;
if (len && !src) {
errno = EINVAL;
return NULL;
}
mem = malloc(len + sizeof (struct mem_factory));
if (!mem) {
errno = ENOMEM;
return NULL;
}
mem->produce = mem_producer;
mem->retire = mem_retirer;
mem->size = len;
if (len > 0)
memcpy(mem->data, src, len);
return (struct any_factory *)mem;
}
Essentially, the struct any_factory type is actually polymorphic (not in the application, but within the library only). All its variants (struct mem_factory here) has the two initial function pointers in common.
Now, if we examine the code above, and consider the factory pattern, you should realize that the function pointers provide very little of value: you could just use the polymorphic type I showed earlier in this answer, and have the inline producer and consumer functions call subtype-specific internal functions based on the type of the factory. factory.h:
#ifndef FACTORY_H
#define FACTORY_H
#include <stdlib.h>
struct factory {
/* Common member across all factory types */
const int type;
/* Flexible array member to stop applications
from declaring static factories. */
const unsigned long data[];
};
/* Generic producer function */
void *produce(const struct factory *);
/* Generic factory discard function */
void retire(struct factory *);
/*
* Library functions that return factories.
*/
struct factory *mem_factory(const void *, const size_t);
#endif /* FACTORY_H */
and factory.c:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "factory.h"
enum {
INVALID_FACTORY = 0,
/* List of known factory types */
MEM_FACTORY,
/* 1+(the highest known factory type) */
NUM_FACTORY_TYPES
};
struct mem_factory {
int type;
size_t size;
char data[];
};
/* The visibility of this union ensures the initial sequences
in the structures are compatible; see C11 6.5.2.3p6.
Essentially, this causes the casts between these structure
types, for accessing their initial common members, valid. */
union all_factories {
struct factory factory;
struct mem_factory mem_factory;
};
/* All factories thus far implemented
are a single structure dynamically
allocated, which makes retiring simple.
*/
void retire(struct factory *factory)
{
if (factory &&
factory->type > INVALID_FACTORY &&
factory->type < NUM_FACTORY_TYPES) {
/* Poison factory type, to make it easier
to detect use-after-free bugs. */
factory->type = INVALID_FACTORY;
free(factory);
}
}
char *mem_producer(struct mem_factory *mem)
{
/* As a courtesy for users, return the memory
padded to a length multiple of 16 chars
with zeroes. No real reason to do this. */
const size_t size = (mem->size | 7) + 9;
char *result;
result = malloc(size);
if (!result) {
errno = ENOMEM;
return NULL;
}
/* Clear padding. */
memset(result + size - 16, 0, 16);
/* Copy data, if any. */
if (mem->size)
memcpy(result, mem->data, mem->size);
return result;
}
/* Generic producer function.
Calls the proper individual producers.
*/
void *factory_producer(struct factory *factory)
{
if (!factory) {
errno = EINVAL;
return NULL;
}
switch (factory->type) {
case mem_factory:
return mem_producer((struct mem_factory *)factory);
default:
errno = EINVAL;
return NULL;
}
}
/* Library functions that return factories.
*/
struct factory *mem_factory(const void *ptr, const size_t len)
{
struct mem_factory *mem;
if (!ptr && len > 0) {
errno = EINVAL;
return NULL;
}
mem = malloc(len + sizeof (struct mem_factory));
if (!mem) {
errno = ENOMEM;
return NULL;
}
mem->type = MEM_FACTORY;
mem->size = len;
if (len > 0)
memcpy(mem->data, ptr, len);
return (struct factory *)mem;
}
If we look at standard C and POSIX C library implementations, we'll see that both of these approaches are used.
The standard I/O FILE structure often contains function pointers, and the fopen(), fread(), fwrite(), etc. functions are just wrappers around these. This is especially the case if the C library supports an interface similar to GNU fopencookie().
POSIX.1 socket, especially the struct sockaddr type, is the original prototype for the polymorphic structure shown first in this answer. Because their interface does not support anything similar to fopencookie() (that is, overriding the implementation of e.g. send(), recv(), read(), write(), close()), there is no need for the function pointers.
So, please do not ask which one is more suitable, as both are very commonly used, and it very much depends on minute details.. In general, I prefer the one that yields a simpler implementation providing all the necessary functionality.
I have personally found that it is not that useful to worry about future use cases without practical experience and feedback first. Rather than trying to create the end-all, best-ever framework that solves all future problems, the KISS principle and the Unix philosophy seem to yield much better results.
(Quoting your accepted answer to yourself)
Secondly a pointer to a parent struct can't receive a pointer to it's derived type (Embedded parent struct) so I can't do much there. I tried using void * but perhaps a solution might exists using memory address and then access some member of the struct without casting to specific types. I'll ask that in another question.
This is yet another pointer that one should learn the basics first. The thing you miss is called 'forward declaration':
struct chicken; // here we tell the compiler that 'struct chicken' is a thing
struct egg{
struct chicken *laidby; // while the compiler knows no details about 'struct chicken',
// its existence is enough to have pointers for it
};
struct chicken{ // and later it has to be declared properly
struct egg *myeggs;
};
What I'm missing is the ability to call the super method from the overridden run method in some way?
These are not methods and there is no override. In your code no OOP happens, C is a procedural programming language. While there are OOP extensions for C, you really should not go for them without knowing C basics.
First community told me that anonymous functions are not part of C, so the alternate suggestion is to use named functions and pointer to it.
Secondly a pointer to a parent struct can't receive a pointer to it's derived type (Embedded parent struct) so I can't do much there. I tried using void * but perhaps a solution might exists using memory address and then access some member of the struct without casting to specific types. I'll ask that in another question.
What I'm missing is the ability to call the super method from the overridden run method in some way?
src/super.h
struct Super {
void (*run)();
};
struct Super *newSuper();
src/super.c
static void run() {
printf("Running super struct\n");
}
struct Super *newSuper() {
struct Super *super = malloc(sizeof(struct Super));
super->run = run;
return super;
}
src/Runner.h
struct Runner {
void (*addFactoryMethod)(struct Super *(*ref)());
void (*execute)();
};
struct Runner *newRunner();
src/runner.c
struct Super *(*superFactory)();
void addFactoryMethod(struct Super *(*ref)()) {
superFactory = ref;
}
static void execute() {
struct Super *sup = superFactory(); // calling cached factory method
sup->run();
}
struct Runner *newRunner() {
struct Runner *runner = malloc(sizeof(struct Runner));
runner->addFactoryMethod = addFactoryMethod;
runner->execute = execute;
return runner;
}
test/runner_test.c
void anotherRunMethod() {
printf("polymorphism working\n");
// how can i've the ability to call the overridden super method in here?
}
struct Super *newAnotherSuper() {
struct Super *super = malloc(sizeof(struct Super));
super->run = anotherRunMethod;
return super;
}
void testSuper() {
struct Runner *runner = newRunner();
runner->addFactoryMethod(&newAnotherSuper);
runner->execute();
}
int main() {
testSuper();
return 0;
}

Good Coding Practice With C structs?

In C, you can define structures to hold an assortment of variables;
typedef struct {
float sp;
float K; // interactive form - for display only
float Ti; // values are based in seconds
float Td;
} pid_data_t;
But lets say that K, Ti, and Td should never be set publicly, and should only be used for storing the values after they have been manipulated. So, I want these values not to be updated by;
pid_data_t = pid_data;
pid_data.K = 10; // no good! changing K should be done via a function
I want them to be set via a function;
int8_t pid_set_pid_params(float new_K_dash, float new_Ti_dash,
float new_Td_dash)
{
… // perform lots of things
pid_data->K = new_K_dash;
pid_data->Ti = new_Ti_dash;
pid_data->Td = new_Td_dash;
}
Any thoughts on this? I know C++ uses like a get/set property, but was wondering what people might do on C.
Your public interface should only offer an opaque pointer (maybe DATA*, or data_handle), as well as handler functions create_data(), set_data_value(), read_data_value(), free_data(), etc., which operate on the opaque pointer.
Much like FILE*.
Just don't give your clients the internal header files :-)
// library.h
typedef struct data_t * data_handle;
data_handle create_data();
void free_data(data_handle);
Private implementation (don't ship):
#include "library.h"
struct data_t
{
/* ... */
};
data_handle create_data() { return malloc(sizeof(struct data_t)); }
void free_data(data_handle h) { free(h); }
/* etc. etc. */
in C, by convention....
for OO C like this...
I'd have a pid_data_create(&data) // initializes your struct
and pid_data_set_proportional_gain(&data, 0.1);
etc...
so basically achieving a C++ ish class... prefix all functions with the "class" / "struct" name and always pass the struct * as the first parameter.
also, it should store function pointers for polymorphisim, and you shouldn't call those function pointers directly, again, have a function that takes your struct as a parameter, and then the can make the function pointer call (can check for nulls, fake inheritance/virtual functions, and other stuff)
The canonical way to do this is by using a combination of opaque pointers and public structs, along with allocators, getters and setters for the private elements. About along these lines:
foo.h
typedef struct Foo {
/* public elements */
} Foo;
Foo *new_Foo(void);
void Foo_something_opaque(Foo* foo);
foo.c
#include "foo.h"
typedef struct Private_Foo_ {
struct Foo foo;
/* private elements */
} Private_Foo_;
Foo *new_Foo(void)
{
Private_Foo_ *foo = malloc(sizeof(Private_Foo_));
/* initialize private and public elements */
return (Foo*) foo;
}
void Foo_something_opaque(Foo *foo)
{
Private_Foo_ *priv_foo = (Private_Foo_*) foo;
/* do something */
}
This woks, because C guarantees, that the address of a struct variable always is equal to the address of the very first struct element. We can use this to have a Private_Foo_ struct, containing a public Foo at the beginning, giving out pointers to the whole thing, with the compilation units not having access to the Private_Foo_ struct defintion just seeing some memory without any context.
It should be noted that C++ works quite similar behind the curtains.
Update
As KereekSB pointed out, this will break if used in a array.
I say: Then don't make Foo f[], however tempting, but make an arrays of pointers to Foo: Foo *f[].
If one really insists on using it in arrays do the following:
foo_private.h
typedef struct Private_Foo_ {
/* private elements */
} Private_Foo_;
static size_t Private_Foo_sizeof(void) { return sizeof(Private_Foo_); }
foo_private.h is written in a way, that it can be compiled into an object file. Use some helper program to link it and use the result of Private_Foo_sizeof() to generate the actual, plattform dependent foo.h from some foo.h.in file.
foo.h
#include
#define FOO_SIZEOF_PRIVATE_ELEMENTS <generated by preconfigure step>
typedef struct Foo_ {
/* public elements */
char reserved[FOO_SIZEOF_PRIVATE_ELEMENTS];
} Foo;
Foo *new_Foo(void);
void Foo_something_opaque(Foo* foo);
foo.c
#include "foo.h"
#include "foo_private.h"
Foo *new_Foo(void)
{
Foo *foo = malloc(sizeof(Foo));
/* initialize private and public elements */
return (Foo*) foo;
}
void Foo_something_opaque(Foo *foo)
{
Private_Foo_ *priv_foo = (Private_Foo_*) foo.reserved;
/* do something */
}
IMHO this is really messy. Now I'm a fan of smart containers (unfortunately there's no standard container library for C). Anyway: In such a container is creates through a function like
Array *array_alloc(size_t sizeofElement, unsigned int elements);
void *array_at(Array *array, unsigned int index);
/* and all the other functions expected of arrays */
See the libowfaw for an example of such an implementation. Now for the type Foo it was trivial to provide a function
Array *Foo_array(unsigned int count);
Object orientation is a way of thinking and modelling, data encapsulation where struct data should not be modified directly by the user can be implemented this way:
my_library.h
#ifndef __MY_LIBRARY__
#define __MY_LIBRARY__
typedef void MiObject;
MyObject* newMyObject();
void destroyMyObject(MyObject*)
int setMyObjectProperty1(MyObject*,someDataType1*);
/*Return a pointer to the data/object, classic pass by value */
someDataType1* getMyObjectProperty2Style1(MyObject*);
int setMyObjectProperty2(MyObject*,someDataType2*);
/* The data/object is passed through reference */
int getMyObjectProperty2Style2(MyObject*,someDataType2**);
/* Some more functions here */
#endif
my_library.c
struct _MyHiddenDataType{
int a;
char* b;
..
..
};
MyObject* newMyObject(){
struct _MyHiddenData* newData = (struct _MyHiddenData*)malloc(sizeof(struct _MyHiddenData);
//check null, etc
//initialize data, etc
return (MyObject*)newData;
}
int setMyObjectProperty1(MyObject* object,someDataType1* somedata){
struct _MyHiddenData* data = (struct _MyHiddenData*)object;
//check for nulls, and process somedata
data->somePropery=somedata;
}
someDataType1* getMyObjectProperty2Style1(MyObject*){
struct _MyHiddenData* data = (struct _MyHiddenData*)object;
//check for nulls, and process somedata
return data->someProperty;
}
/* Similar code for the rest */
And this way you have encapsulated the struct properties as if they were private. On the same manner static functions inside my_libray.c would behave as private functions. Get a good look at C and you'll see, that your imagination is the limit to what you can do.

Do all C compilers allow functions to return structures?

I am working on a program in C and using the SDCC compiler for a 8051 architecture device.
I am trying to write a function called GetName that will read 8 characters from Flash Memory and return the character array in some form. I know that it is not possible to return an array in C so I am trying to do it using a struct like this:
//********************FLASH.h file*******************************
MyStruct GetName(int i); //Function prototype
#define NAME_SIZE 8
typedef struct
{
char Name[NAME_SIZE];
} MyStruct;
extern MyStruct GetName(int i);
// *****************FLASH.c file***********************************
#include "FLASH.h"
MyStruct GetName( int i)
{
MyStruct newNameStruct;
//...
// Fill the array by reading data from Flash
//...
return newNameStruct;
}
I don't have any references to this function yet but for some reason, I get a compiler error that says "Function cannot return aggregate." Does this mean that my compiler does not support functions that return structs? Or am I just doing something wrong?
SDCC doesn't support assignment and returning structs yet (if their Wiki is up-to-date):
Not yet implemented in sdcc:
Data type double.
Structures and unions can not be assigned, passed as function parameters or return values.
register storage class specifier in function parameters.
Maybe you should make a
void GetName(MyStruct* ret_name, int i);
function instead.
That said, you should put the function prototype before the main and after the MyStruct. If there's no prototypes a function will be assumed to return int.
MyStruct GetName(int i);
void main(void) { ...
(Also, the main function should be an int main(void) or int main(int argc, char** argv). It shouldn't return void.)
All post-ANSI C89/90 compilers allow returning struct objects. Classic (pedantic) K&R C compilers do not.
However, in any case you have to declare the function first. i.e. before you call it. And char[8] Name inside your struct is not a valid declaration. The valid form is char Name[8].
Your pointer-to-array-returning function is declared correctly. It is your size macro that's broken. Should be
#define NAME_SIZE 8
Note: no = character.
Yes, functions can return structs in C. Your code above has several errors. With a few changes, It compiles correctly under gcc (I don't have sdcc installed to try with, but please try the code below.
struct MyStruct
{
char Name[8];
};
struct MyStruct GetName( int i)
{
struct MyStruct newNameStruct;
//...
// Fill the array by reading data from Flash
//...
return newNameStruct;
}
int main(void)
{
int NameIndex = 3;
struct MyStruct testStruct;
testStruct = GetName(NameIndex);
return 0;
}
I really wouldn't want to use a C compiler that didn't implement structure call and return by value, as KennyMT suggests yours doesn't. In fact, such a compiler should not really be called a C compiler. If the compiler implements structures at all, return by value is not hard to implement.
Anyway, to work with your compiler you will want something like:
typedef struct
{
char Name[NAME_SIZE];
} MyStruct;
void f( MyStruct * m ) {
strcpy( m->Name, "foo" );
}
int main() {
MyStruct ms;
f( & ms );
return 0;
}

Is there any way to pass a structure type to a c function

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")
}

Resources