segfault in a C garbage collector - c

I'm building a simple garbage collector in C, with a void pointer linked list that collects the malloced pointers and frees them all at the end.
#include "linked_list.h"
#define MAKE_GC(NAME) \
MAKE_LIST(NAME); \
static void _throw_away_##NAME() { \
ITERATOR(NAME) = &NAME; \
do { \
free(ITERATOR(NAME)->elem); \
} while ((ITERATOR(NAME) = ITERATOR(NAME)->next) != NULL); \
DESTROY_LIST(NAME); \
}
#define GC_ALLOC(TYPE, TARGET, LEN, GC_NAME) \
do { \
TARGET = (TYPE *)malloc(LEN * sizeof(TYPE)); \
PUSH(TYPE *, TARGET, GC_NAME); \
} while (0)
#define GC_FREE(NAME) _throw_away_##NAME()
The above is the garbage collector, and below is linked_list.h
struct linked_list {
void *elem;
struct linked_list *next;
};
#define ITERATOR(LIST_NAME) _iter_##LIST_NAME
#define MAKE_LIST(NAME) \
struct linked_list NAME = { NULL, NULL }; \
struct linked_list *ITERATOR(NAME) = &NAME
#define PUSH(TYPE, X, LIST) \
do { \
ITERATOR(LIST) = ITERATOR(LIST)->next = (struct linked_list *)malloc(sizeof(struct linked_list)); \
*(TYPE *)ITERATOR(LIST)->elem = X; \
ITERATOR(LIST)->next = NULL; \
} while (0)
#define DESTROY_LIST(LIST) \
do { \
struct linked_list *l; \
ITERATOR(LIST) = &LIST; \
do { \
l = ITERATOR(LIST)->next; \
free(ITERATOR(LIST)); \
} while ((ITERATOR(LIST) = l) != NULL); \
} while (0)
When I test this code with the following,
#include <stdio.h>
#include "garbage_collector.h"
MAKE_GC(char_gc);
int main() {
char *str;
int i;
GC_ALLOC(char, str, 11, char_gc);
for (i = 0; i < 10; i++) {
putchar(str[i] = i + '0');
}
str[i] = '\0';
putchar('\n');
puts(str);
GC_FREE(char_gc);
return 0;
}
It runs as expected, although the debuggers (gdb and Visual Studio debugger) keep on throwing segfaults in GC_ALLOC. It's a really short piece of code, and I'm quite annoyed that I still have no clue where it goes wrong.
I want to be sure where my program is broken and fix it before implementing elsewhere. Thanks in advance for any help.

In your PUSH macro, I don't think this line is correct:
*(TYPE *)ITERATOR(LIST)->elem = X; \
I think you want something like this:
ITERATOR(LIST)->elem = (void *)X; \
In your code, I get a seg fault here:
GC_ALLOC(char, str, 11, char_gc);
and it's due to the fact that GC_ALLOC does a PUSH, passing str as X. Once str has been properly allocated by the previous line, you want to assign the pointer to elem, but your code attempts to dereference elem, and then assign the pointer to that dereferenced item. dereferencing elem is illegal at that point, and seg faults, because it has not been allocated (and should not be at that point).
After that, you have a problem at the final GC_FREE in your code, because it eventually tries to free an unallocated pointer. When GC_FREE attempts to DESTROY_LIST(gc_Char), it starts with the first item in the list. But this item was not allocated via malloc (take a look at MAKE_LIST), so it cannot be free'd using free. So we have to skip past this first item in the list when we want to DESTROY_LIST. The following code has these items fixed and seems to work correctly for your test case:
#include <stdio.h>
#include <stdlib.h>
struct linked_list {
void *elem;
struct linked_list *next;
};
#define ITERATOR(LIST_NAME) _iter_##LIST_NAME
#define MAKE_LIST(NAME) \
struct linked_list NAME = { NULL, NULL }; \
struct linked_list *ITERATOR(NAME) = &NAME
#define PUSH(TYPE, X, LIST) \
do { \
ITERATOR(LIST) = ITERATOR(LIST)->next = (struct linked_list *)malloc(sizeof(struct linked_list)); \
ITERATOR(LIST)->elem = (void *)X; \
ITERATOR(LIST)->next = NULL; \
} while (0)
#define DESTROY_LIST(LIST) \
do { \
struct linked_list *l; \
ITERATOR(LIST) = &LIST; \
l = ITERATOR(LIST)->next; \
while ((ITERATOR(LIST) = l) != NULL) { \
l = ITERATOR(LIST)->next; \
free(ITERATOR(LIST)); \
} \
} while (0)
#define MAKE_GC(TYPE, NAME) \
MAKE_LIST(NAME); \
static void _throw_away_##NAME() { \
ITERATOR(NAME) = &NAME; \
do { \
free(ITERATOR(NAME)->elem); \
} while ((ITERATOR(NAME) = ITERATOR(NAME)->next) != NULL); \
DESTROY_LIST(NAME); \
}
#define GC_ALLOC(TYPE, TARGET, LEN, GC_NAME) \
do { \
TARGET = (TYPE *)malloc(LEN * sizeof(TYPE)); \
PUSH(TYPE *, TARGET, GC_NAME); \
} while (0)
#define GC_FREE(NAME) _throw_away_##NAME()
MAKE_GC(char, char_gc);
int main() {
char *str;
int i;
GC_ALLOC(char, str, 11, char_gc);
for (i = 0; i < 10; i++) {
putchar(str[i] = i + '0');
}
str[i] = '\0';
putchar('\n');
puts(str);
GC_FREE(char_gc);
return 0;
}

Related

Can anyone recommend a way to write a function that counts the number of fields in a struct? i.e. - pseudocode- 'for field in struct'

I want a C function that I can pass a structure to and it will return the number of fields/members within the structure.
At the moment I've found the easiest way is to just make a table and add to the table anytime I add a struct to any of the programs.
I guess I'm experiencing an XY problem (per the suggestions) So anyway, the reason why I would have use for this type function is because I'm wanting to send structures over a socket and to avoid the whole serialization process the way in which i'm trying to do this is by adding delimiters to the structure's field members. Like this:
0x001 --> hdrdata --> 0x003 --> hdrdata --> 0x017 --> 0x002 --> bodydata --> 0x003 --> bodydata --> 0x003 --> bodydata --> 0x004
As you can see there may be 1 bodydata or there may be 10 bodydata etc. The only other thing I can quickly think to do is add a member to my structs that would inform my header how many 'bodydata' transmissions will be coming through so the client knows how many 0x003's to expect.
Or (and i'm not asking for an answer to this but feel free if you are so inclined) can anyone recommend a better protocol design for sending structures over socket in unix? Most of this project is for my own learning so i'm not interested in using an already complete library/package solution otherwise i'd just be writing this in another language in the first place.
This is very very ugly, but the only thing I can think of is an X-Macro:
#include <stdio.h>
#define MEMBERS \
X(char a) \
X(float b) \
X(double c)
struct T {
#define X(x) x;
MEMBERS
#undef X
};
int main(void)
{
size_t n = 0
#define X(x) +1
MEMBERS
#undef X
;
printf("%zu members\n", n);
return 0;
}
This expands to:
#include <stdio.h>
struct T {
char a;
float b;
double c;
};
int main(void)
{
size_t n = 0+1+1+1;
printf("%zu members\n", n);
return 0;
}
As pointed out by #HAL9000 in comments, you can generate both (the struct and the counter) at the same time in this way:
#include <stdio.h>
#define GENERATE_STRUCT(s) s;
#define GENERATE_SCOUNT(s) +1
#define set_struct(name) \
struct name { \
name##_members(GENERATE_STRUCT) \
}; \
\
size_t name##_count(void) \
{ \
return 0 \
name##_members(GENERATE_SCOUNT) \
; \
}
#define foo_members(X) \
X(char a) \
X(float b) \
X(double c)
set_struct(foo)
int main(void)
{
printf("%zu members\n", foo_count());
return 0;
}
In this case is expanded to:
#include <stdio.h>
struct foo {
char a;
float b;
double c;
};
size_t foo_count(void)
{
return 0+1+1+1;
}
int main(void)
{
printf("%zu members\n", foo_count());
return 0;
}
Finally, another implementation provided by #Lundin using an enum instead of a variable:
#include <stdio.h>
#define MEMBERS \
/* type name */ \
X(char, a) \
X(float, b) \
X(double, c) \
struct T {
#define X(type, name) type name;
MEMBERS
#undef X
};
enum
{
#define X(type, name) dummy_##name,
MEMBERS
#undef X
MEMBER_COUNT
};
int main(void)
{
printf("%d members\n", MEMBER_COUNT);
return 0;
}
Expands to:
#include <stdio.h>
struct T {
char a;
float b;
double c;
};
enum {
dummy_a,
dummy_b,
dummy_c,
MEMBER_COUNT
};
int main(void)
{
printf("%d members\n", MEMBER_COUNT);
return 0;
}

Set a function argument with function pointers

In C is there a way to set a function argument using function pointers such that all calls to that function pointer just use the set parameter? As an example, is it possible to do something like the code below?
void do_something(int *a, int *b, int *c){
*a = *c - 5;
*b = *c - 10;
}
typedef void (*funcptr)(int *a, int *b, int *c);
int main(){
int num = 5;
funcptr f = do_something(c=&num); // c = 5 for all calls to f(a, b)
int *a; int *b;
f(a, b); //a = 0, b = -5
num = 10;
f = do_something(c=&num); // c = 10 for all calls to f(a, b)
f(a, b); //a = 5, b = 0
}
This seems possible with external C libraries like Blocks and FFCALL, but it appears I'd need to set a, b, and c instead of setting a single argument.
no, this is not a language feature of C or of the C calling convention.
You'll need to construct function that calls your function pointer with that argument yourself; external libraries that provide such functionality are available, as you've noticed.
Another way, though I'm personally not overly fond of that is using <stdarg> and varargs, letting your function do one thing or another, depending on the number of arguments passed.
In C frameworks, you'll often find a lot of functions that work in some kind of context. That is often even used in implementation of object-oriented programming. I don't know the larger picture of what you want to implement, but often questions like these are rised in a context where someone wants to do something that resembles function overloading in C++; if that's the case, you might really just make functions that take a "state/context" argument, and further arguments, which might or might not be relevant, depending on the state.
Rather than using function pointers, you would need a wrapper function that uses a global for state.
void do_something(int *a, int *b, int c){
*a = c - 5;
*b = c - 10;
}
static int c_val = NULL;
void do_something_wrap(int *a, int *b)
{
do_something(a, b, c);
}
int main(){
int num = 5;
c_val = num;
int a; int b;
do_something_wrap(&a, &b); //a = 0, b = -5
num = 10;
c_val = num;
do_something_wrap(&a, &b); //a = 5, b = 0
}
C has no such features like default arguments or function overloading.
Moreover in this declaration
funcptr f = do_something;
the initializer shall be a function pointer.
Standard C has no such facility. Compilers offer extensions that allow this though. Nested functions in GCC, Blocks in clang or via a library like CALLBACK in clisp or assembling your call via libffi.
[..] is there a way [..] ?
There always is a way. The question is if it's worth the effort and possible downsides.
The following is based on another answer I gave about deferred (that is, called e.g. at the end of scope) function execution.
Start off with a unified type for a "partially applied function":
struct partially_applied {
void * data; // parameters
void (*function)(void *); // function unpacking parameters and calling actual function
void (*store)(void *, char const *, void *); // storing parameters
};
typedef struct partially_applied * FUN;
To make a function partially apply-able we need
a struct holding the (eventually) already applied parameters (I added an init function and an allocation function)
a function to unpack these and call the actual function
a function to store ("partially apply") parameters
Here we go:
#define MAKE_PARTIAL(fn, N, ...) \
struct partially_applied_ ## fn ## _data { \
DATA_DEF(N, __VA_ARGS__) \
}; \
\
static void init_partially_applied_ ## fn ## _data (void * p) { \
struct partially_applied_ ## fn ## _data * data = p; \
DATA_INIT(N, __VA_ARGS__); \
} \
\
static void * allocate_partially_applied_ ## fn ## _data (void) { \
void * data = malloc(sizeof(struct partially_applied_ ## fn ## _data)); \
if (data == NULL) { \
fprintf(stderr, "Allocation failure for " #fn " data\n"); \
exit(1); \
} \
init_partially_applied_ ## fn ## _data(data); \
return data; \
} \
\
static void partially_applied_ ## fn (void * p) { \
struct partially_applied_ ## fn ## _data * data = p; \
if (DATA_CHECK(N, __VA_ARGS__)) { \
fn(DATA_ACCESS(N, __VA_ARGS__)); \
} else { \
fprintf(stderr, "Not all parameters for " #fn " are vaild\n"); \
} \
} \
\
static void partially_applied_ ## fn ## _store ( \
void * p, char const * id, void * src) { \
struct partially_applied_ ## fn ## _data * data = p; \
DATA_STORE_CODE(N, __VA_ARGS__) \
fprintf(stderr, "Cannot store %s in " #fn "!\n", id); \
}
The above contains some macros. These depend on the number of macro arguments (which could be counted by the preprocessor, but I want to keep it simpler). To expand the correct macro (depending on the number of arguments) we need a little helper:
#define SPLICE_2(l,r) l##r
#define SPLICE_1(l,r) SPLICE_2(l,r)
#define SPLICE(l,r) SPLICE_1(l,r)
Now on to the macros. DATA_DEF defines the structure contents:
#define DATA_DEF_0(...)
#define DATA_DEF_1(type, name) type name; bool name ## _valid;
#define DATA_DEF_2(type, name, ...) type name; bool name ## _valid; DATA_DEF_1(__VA_ARGS__)
#define DATA_DEF_3(type, name, ...) type name; bool name ## _valid; DATA_DEF_2(__VA_ARGS__)
#define DATA_DEF_4(type, name, ...) type name; bool name ## _valid; DATA_DEF_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_DEF(N, ...) SPLICE(DATA_DEF_,N)(__VA_ARGS__)
DATA_INIT expands to code to initialize such a structure:
#define DATA_INIT_0(...)
#define DATA_INIT_1(t, name) data->name ## _valid = false;
#define DATA_INIT_2(t, name, ...) data->name ## _valid = false; DATA_INIT_1(__VA_ARGS__)
#define DATA_INIT_3(t, name, ...) data->name ## _valid = false; DATA_INIT_2(__VA_ARGS__)
#define DATA_INIT_4(t, name, ...) data->name ## _valid = false; DATA_INIT_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_INIT(N, ...) SPLICE(DATA_INIT_,N)(__VA_ARGS__)
DATA_CHECK expands to a condition testing if all arguments have been applied:
#define DATA_CHECK_0(...) true
#define DATA_CHECK_1(t, name) data->name ## _valid
#define DATA_CHECK_2(t, name, ...) data->name ## _valid && DATA_CHECK_1(__VA_ARGS__)
#define DATA_CHECK_3(t, name, ...) data->name ## _valid && DATA_CHECK_2(__VA_ARGS__)
#define DATA_CHECK_4(t, name, ...) data->name ## _valid && DATA_CHECK_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_CHECK(N, ...) SPLICE(DATA_CHECK_,N)(__VA_ARGS__)
DATA_ACCESS expands into code for passing the parameters to the actual function (actually it's only the comma separated arguments list):
#define DATA_ACCESS_0(...)
#define DATA_ACCESS_1(t, name) data->name
#define DATA_ACCESS_2(t, name, ...) data->name, DATA_ACCESS_1(__VA_ARGS__)
#define DATA_ACCESS_3(t, name, ...) data->name, DATA_ACCESS_2(__VA_ARGS__)
#define DATA_ACCESS_4(t, name, ...) data->name, DATA_ACCESS_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_ACCESS(N, ...) SPLICE(DATA_ACCESS_,N)(__VA_ARGS__)
And finally DATA_STORE_CODE expands into code to store the parameters:
#define DATA_STORE_CODE_OP(type, name) \
if (strcmp(id, #name) == 0) { data->name = *((type *) src); data->name ## _valid = true; return; }
#define DATA_STORE_CODE_0(...)
#define DATA_STORE_CODE_1(type, name) DATA_STORE_CODE_OP(type, name)
#define DATA_STORE_CODE_2(type, name, ...) DATA_STORE_CODE_OP(type, name) DATA_STORE_CODE_1(__VA_ARGS__)
#define DATA_STORE_CODE_3(type, name, ...) DATA_STORE_CODE_OP(type, name) DATA_STORE_CODE_2(__VA_ARGS__)
#define DATA_STORE_CODE_4(type, name, ...) DATA_STORE_CODE_OP(type, name) DATA_STORE_CODE_3(__VA_ARGS__)
// more
#define DATA_STORE_CODE(N, ...) SPLICE(DATA_STORE_CODE_,N)(__VA_ARGS__)
Adding little helpers to allocate and free partially applied function structures (data is expected to be allocated by malloc here) ...
FUN make_fun(void (*function)(void *), void (*store)(void *, char const *, void *), void * data) {
FUN f = malloc(sizeof(*f));
if (f == NULL) {
fprintf(stderr, "Allocation of FUN failed\n");
exit(1);
}
f->function = function;
f->store = store;
f->data = data;
return f;
}
void free_fun(FUN f) {
free(f->data);
free(f);
}
... we can go on to define a macro that actually makes an instance of a partially applied function:
#define PARTIAL(fn) make_fun(&(partially_applied_ ## fn), \
&(partially_applied_ ## fn ## _store), \
allocate_partially_applied_ ## fn ## _data())
Of course we want to be able to apply some arguments:
#define APPLY(PFN, N, ...) \
do { \
struct partially_applied * pfn = (PFN); \
DATA_STORE(N, __VA_ARGS__) \
} while(0)
The macro DATA_STORE expands into code to call the store functions multiple times, so that we can apply multiple arguments at once:
#define DATA_STORE_OP(name, value) pfn->store(pfn->data, #name, &(value));
#define DATA_STORE_0(...)
#define DATA_STORE_1(name, value) DATA_STORE_OP(name, value)
#define DATA_STORE_2(name, value, ...) DATA_STORE_OP(name, value) DATA_STORE_1(__VA_ARGS__)
#define DATA_STORE_3(name, value, ...) DATA_STORE_OP(name, value) DATA_STORE_2(__VA_ARGS__)
#define DATA_STORE_4(name, value, ...) DATA_STORE_OP(name, value) DATA_STORE_3(__VA_ARGS__)
#define DATA_STORE(N, ...) SPLICE(DATA_STORE_,N)(__VA_ARGS__)
Last but not least we want to be able to call such a function (this could also be a function, but well):
#define CALL(fn) (fn)->function((fn)->data)
Finally, an example:
void foo(char * str, int i) {
printf("FOO| str = %s, i = %d\n", str, i);
}
void bar(float f, int i, size_t s) {
printf("BAR| f = %f, i = %d, s = %zu\n", f, i, s);
}
MAKE_PARTIAL(foo, 2, char *, string, int, integer)
MAKE_PARTIAL(bar, 3, float, floating, int, INT, size_t, SOME_SIZE)
int main() {
FUN f = PARTIAL(foo);
char * c = "Crazy";
APPLY(f, 1, string, c);
printf("doing other stuff\n");
FUN g = PARTIAL(bar);
size_t size = 99;
APPLY(g, 1, SOME_SIZE, size);
int answer = 42;
APPLY(f, 1, integer, answer);
answer = 21;
float pi = 3.14;
APPLY(g, 2, INT, answer, floating, pi);
CALL(f);
printf("done\n");
CALL(g);
printf("now completely done\n");
return 0;
}
Some downsides:
macros. macros everywhere.
Losing some type safety (in APPLY)
Need for lvalues (APPLY(f, 1, integer, 42) does not work)

C Preprocessor macros extension concatenation

Suppose I would like to use the C Preprocessor to define a family of function, for which only a parameter type changes. Let's take for example allocation functions with parameters:
#include <stdint.h>
#include <stdio.h>
#define type_vector(t) \
t * t##vector(int32_t nl, int32_t nh) \
{ \
t * v = NULL; /* malloc(...) */ \
return v; \
}
type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)
int main() {
int32_t * p;
p = int32_tvector(10, 12);
return 0;
}
This works fine.
Now, suppose I would like to have shorter names for type in the function names: i8 instead of int8_t, i32 instead of int32_t, etc.
I do not want to add a second parameter to the macro function declaration, but instead have a single definition of "short" type names.
Basically, the first thing I wrote was:
#define sn_int8_t i8
#define sn_int32_t i32
#define sn_int64_t i64
#define sn(t) sn_##t
#define type_vector(t) \
t * sn(t)##vector(int32_t nl, int32_t nh) \
{ \
t * v = NULL; /* malloc(...) */ \
return v; \
}
type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)
int main() {
int32_t * p;
p = i32vector(10, 12);
return 0;
}
However, this does not compile, giving the following error:
error: pasting ")" and "vector" does not give a valid preprocessing token
t * sn(t)##vector(int32_t nl, int32_t nh) \
As far as I understood, the problem is due to having the ")" and the "#" side by side.
So I did the following:
#define sn_int8_t(f) i8##f
#define sn_int32_t(f) i32##f
#define sn_int64_t(f) i64##f
#define sn2(t,f) sn_##t(f)
#define type_vector(t) \
t * sn2(t,vector)(int32_t nl, int32_t nh) \
{ \
t * v = NULL; /* malloc(...) */ \
return v; \
}
type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)
int main() {
int32_t * p;
p = i32vector(10, 12);
return 0;
}
And this works fine again.
Now, suppose I would like to add a prefix to the function name, e.g. "remote_".
Simply putting
#define type_vector(t) \
t * remote_##sn2(t,vector)(int32_t nl, int32_t nh) \
{ \
t * v = NULL; /* malloc(...) */ \
return v; \
}
does not work, as sn2 is not expanded. So I tried this:
#include <stdint.h>
#include <stdio.h>
#define sn_int8_t(f) i8##f
#define sn_int32_t(f) i32##f
#define sn_int64_t(f) i64##f
#define sn2(t,f) sn_##t(f)
#define short_name(n,t,f) n##_##sn2(t,f)
#define remote_type_vector(t) \
t * short_name(remote,t,vector)(int32_t nl, int32_t nh) \
{ \
t * v = NULL; \
return v; \
}
remote_type_vector(int8_t)
remote_type_vector(int32_t)
remote_type_vector(int64_t)
int main() {
int32_t * p;
p = remote_i32vector(10, 12);
return 0;
}
Basically, this does not work because the macro sn2 is not expanded, giving me declarations like:
int32_t * remote_sn2(int32_t,vector)
Is there any way to do that?
Note: I do not want to use C++ templates.
Here's a unified solution that should work for all of your needs:
#define sn_int8_t(p,s) p##i8##s
#define sn_int32_t(p,s) p##i32##s
#define sn_int64_t(p,s) p##i64##s
#define sn2(t,p,s) sn_##t(p,s)
#define type_vector(t) \
t * sn2(t,,vector)(int32_t nl, int32_t nh) \
{ \
t * v = NULL; /* malloc(...) */ \
return v; \
}
#define remote_type_vector(t) \
t * sn2(t,remote,vector)(int32_t nl, int32_t nh) \
{ \
t * v = NULL; \
return v; \
}
type_vector(int8_t)
type_vector(int32_t)
type_vector(int64_t)
remote_type_vector(int8_t)
remote_type_vector(int32_t)
remote_type_vector(int64_t)

Is it possible to modify this X-Macro to build a struct, which includes arrays? How?

Found this very helpful Q/A on SO: Is there any way to loop through a struct with elements of different types in C?
but since I am quite new to the whole X-Macro stuff, I was wondering, if and how would it be possible to adapt this example for a struct with arrays - like this:
typedef struct
{
uint8 Addr1[SIZEOF_ADDR];
uint8 Addr2[SIZEOF_ADDR];
uint8 Addr3[SIZEOF_ADDR];
} TEST;
This is what would be to adapt:
//--- first describe the structure, the fields, their types and how to print them
#define X_FIELDS \
X(int, field1, "%d") \
X(int, field2, "%d") \
X(char, field3, "%c") \
X(char *, field4, "%s")
//--- define the structure, the X macro will be expanded once per field
typedef struct {
#define X(type, name, format) type name;
X_FIELDS
#undef X
} mystruct;
My starting point was like this, but I am quite sure, format would have to be something else, or would have to be replaced:
#define X_FIELDS \
X(uint8, Addr1, "%02X") \
X(uint8, Addr2, "%02X") \
X(uint8, Addr3, "%02X")
An address would be something like {0x10,0x12,0x0A} - all of the same size.
Edit:
This is an example how I am using this struct currently, without x-macros:
TEST test = {{0x16,0xA4,0x3},
{0x16,0xA4,0x2},
{0x16,0xA4,0x1}};
printf("%02X",test.addr1[i]);
You've got a reasonable start...
#include <stdio.h>
typedef unsigned char uint8;
enum { SIZEOF_ADDR = 3 };
#define X_FIELDS \
X(uint8, Addr1, "0x%02X") \
X(uint8, Addr2, "0x%02X") \
X(uint8, Addr3, "0x%02X")
//--- define the structure, the X macro will be expanded once per field
typedef struct {
#define X(type, name, format) type name[SIZEOF_ADDR];
X_FIELDS
#undef X
} TEST;
extern void iterate1(TEST *test);
extern void iterate2(TEST *test);
//--- Print the values
void iterate1(TEST *test)
{
const char *pad;
//--- "iterate" over all the fields of the structure
#define X(type, name, format) \
printf("%s is ", #name); \
pad = "{"; \
for (size_t i = 0; i < sizeof(test->name); i++) \
{ \
printf("%s" format, pad, test->name[i]); \
pad = ","; \
} \
printf("}\n");
X_FIELDS
#undef X
}
// Alternatively, define a function `print_addr()`
static void print_addr(const char *format, const uint8 *addr, size_t addrsize)
{
char pad = '{';
for (size_t i = 0; i < addrsize; i++)
{
putchar(pad);
printf(format, addr[i]);
pad = ',';
}
putchar('}');
}
//--- Print the values using print_addr()
void iterate2(TEST *test)
{
//--- "iterate" over all the fields of the structure
#define X(type, name, format) \
printf("%s is ", #name); \
print_addr(format, test->name, sizeof(test->name)); \
printf("\n");
X_FIELDS
#undef X
}
(This code, treated as a single file, is known to compile cleanly under GCC 4.7.1 on Mac OS X 10.7.5.)

How do I return multiple values from a function in C?

If I have a function that produces a result int and a result string, how do I return them both from a function?
As far as I can tell I can only return one thing, as determined by the type preceding the function name.
I don't know what your string is, but I'm going to assume that it manages its own memory.
You have two solutions:
1: Return a struct which contains all the types you need.
struct Tuple {
int a;
string b;
};
struct Tuple getPair() {
Tuple r = { 1, getString() };
return r;
}
void foo() {
struct Tuple t = getPair();
}
2: Use pointers to pass out values.
void getPair(int* a, string* b) {
// Check that these are not pointing to NULL
assert(a);
assert(b);
*a = 1;
*b = getString();
}
void foo() {
int a, b;
getPair(&a, &b);
}
Which one you choose to use depends largely on personal preference as to whatever semantics you like more.
Option 1: Declare a struct with an int and string and return a struct variable.
struct foo {
int bar1;
char bar2[MAX];
};
struct foo fun() {
struct foo fooObj;
...
return fooObj;
}
Option 2: You can pass one of the two via pointer and make changes to the actual parameter through the pointer and return the other as usual:
int fun(char **param) {
int bar;
...
strcpy(*param,"....");
return bar;
}
or
char* fun(int *param) {
char *str = /* malloc suitably.*/
...
strcpy(str,"....");
*param = /* some value */
return str;
}
Option 3: Similar to the option 2. You can pass both via pointer and return nothing from the function:
void fun(char **param1,int *param2) {
strcpy(*param1,"....");
*param2 = /* some calculated value */
}
Since one of your result types is a string (and you're using C, not C++), I recommend passing pointers as output parameters. Use:
void foo(int *a, char *s, int size);
and call it like this:
int a;
char *s = (char *)malloc(100); /* I never know how much to allocate :) */
foo(&a, s, 100);
In general, prefer to do the allocation in the calling function, not inside the function itself, so that you can be as open as possible for different allocation strategies.
Create a struct and set two values inside and return the struct variable.
struct result {
int a;
char *string;
}
You have to allocate space for the char * in your program.
Two different approaches:
Pass in your return values by pointer, and modify them inside the function. You declare your function as void, but it's returning via the values passed in as pointers.
Define a struct that aggregates your return values.
I think that #1 is a little more obvious about what's going on, although it can get tedious if you have too many return values. In that case, option #2 works fairly well, although there's some mental overhead involved in making specialized structs for this purpose.
One approach is to use macros. Place this in a header file multitype.h
#include <stdlib.h>
/* ============================= HELPER MACROS ============================= */
/* __typeof__(V) abbreviation */
#define TOF(V) __typeof__(V)
/* Expand variables list to list of typeof and variable names */
#define TO3(_0,_1,_2,_3) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; TOF(_3) v3;
#define TO2(_0,_1,_2) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2;
#define TO1(_0,_1) TOF(_0) v0; TOF(_1) v1;
#define TO0(_0) TOF(_0) v0;
#define TO_(_0,_1,_2,_3,TO_MACRO,...) TO_MACRO
#define TO(...) TO_(__VA_ARGS__,TO3,TO2,TO1,TO0)(__VA_ARGS__)
/* Assign to multitype */
#define MTA3(_0,_1,_2,_3) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; _3 = mtr.v3;
#define MTA2(_0,_1,_2) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2;
#define MTA1(_0,_1) _0 = mtr.v0; _1 = mtr.v1;
#define MTA0(_0) _0 = mtr.v0;
#define MTA_(_0,_1,_2,_3,MTA_MACRO,...) MTA_MACRO
#define MTA(...) MTA_(__VA_ARGS__,MTA3,MTA2,MTA1,MTA0)(__VA_ARGS__)
/* Return multitype if multiple arguments, return normally if only one */
#define MTR1(...) { \
typedef struct mtr_s { \
TO(__VA_ARGS__) \
} mtr_t; \
mtr_t *mtr = malloc(sizeof(mtr_t)); \
*mtr = (mtr_t){__VA_ARGS__}; \
return mtr; \
}
#define MTR0(_0) return(_0)
#define MTR_(_0,_1,_2,_3,MTR_MACRO,...) MTR_MACRO
/* ============================== API MACROS =============================== */
/* Declare return type before function */
typedef void* multitype;
#define multitype(...) multitype
/* Assign return values to variables */
#define let(...) \
for(int mti = 0; !mti;) \
for(multitype mt; mti < 2; mti++) \
if(mti) { \
typedef struct mtr_s { \
TO(__VA_ARGS__) \
} mtr_t; \
mtr_t mtr = *(mtr_t*)mt; \
MTA(__VA_ARGS__) \
free(mt); \
} else \
mt
/* Return */
#define RETURN(...) MTR_(__VA_ARGS__,MTR1,MTR1,MTR1,MTR0)(__VA_ARGS__)
This makes it possible to return up to four variables from a function and assign them to up to four variables. As an example, you can use them like this:
multitype (int,float,double) fun() {
int a = 55;
float b = 3.9;
double c = 24.15;
RETURN (a,b,c);
}
int main(int argc, char *argv[]) {
int x;
float y;
double z;
let (x,y,z) = fun();
printf("(%d, %f, %g\n)", x, y, z);
return 0;
}
This is what it prints:
(55, 3.9, 24.15)
The solution may not be as portable because it requires C99 or later for variadic macros and for-statement variable declarations. But I think it was interesting enough to post here. Another issue is that the compiler will not warn you if you assign them the wrong values, so you have to be careful.
Additional examples, and a stack-based version of the code using unions, are available at my github repository.
Use pointers as your function parameters.
Then use them to return multiple value.
By passing parameters by reference to function.
Examples:
void incInt(int *y)
{
(*y)++; // Increase the value of 'x', in main, by one.
}
Also by using global variables but it is not recommended.
Example:
int a=0;
void main(void)
{
//Anything you want to code.
}

Resources