S
Shao Miller
Hello Readers,
I'd like to offer some code which some of you might find interesting.
In the code, the func() macro effectively expands to a function which
depends on the type of the argument to the macro. This is useful for
when you wish to treat identifiers differently based on the identified
type. The function can be any function type, returning any type.
Requirements are:
- A "wrapper" type for any type you are interested in using with this
macro
- The wrapper type has a sizeof() being greater than or equal to
sizeof(char*)
- The undefined behaviour due to the "magic" where pointer arithmetic
jumps from one array object to another, dis-joint array object, even
though there are objects of the same type within the latter array
object
I am interested in:
- If anyone can identify an implementation which produces results
different than those found in the demonstration below, or at
http://codepad.org/Cf5zh5xS
- If anyone has any feedback about a "better way" to produce a macro
with similar functionality
The following demonstration can be compiled with 'gcc -ansi -pedantic -
Werror'.
-----
/*
* (C) Shao Miller, 2010
*
* Translation-time type information.
* At the cost of each wrapper type being >= sizeof(char*)
*/
#include <stddef.h>
#include <stdio.h>
enum types {
types_none,
types_char,
types_short,
types_int,
types_long,
types_total
};
union char_wrapper;
typedef char (*char_func_type)(union char_wrapper *this);
union short_wrapper;
typedef short (*short_func_type)(union short_wrapper *this);
/* etc. */
union char_wrapper {
char value;
char (*type)[types_char];
char_func_type func[1];
};
union short_wrapper {
short value;
char (*type)[types_short];
short_func_type func[1];
};
/* etc. */
/* This matches char_func_type */
char char_func(union char_wrapper *this) {
puts("char_func()");
return this->value;
}
/* This matches short_func_type */
short short_func(union short_wrapper *this) {
puts("short_func()");
return this->value;
}
/* etc. */
union any_func {
char_func_type char_func;
short_func_type short_func;
/* etc. */
};
union any_func funcs[types_total];
void init_funcs(void) {
funcs[types_char].char_func = char_func;
funcs[types_short].short_func = short_func;
/* etc. */
}
#define func(x) \
\
(*(x.func - ((char**)x.func - (char**)funcs) + sizeof(*x.type)))(&x)
int main(void) {
union char_wrapper foo;
char foo_test;
union short_wrapper bar;
short bar_test;
init_funcs();
if (sizeof(*foo.type) == types_char) {
puts("foo was indeed a char_wrapper");
}
if (sizeof(*bar.type) == types_short) {
puts("bar was indeed a short_wrapper");
}
foo_test = func(foo);
bar_test = func(bar);
return 0;
}
-----
Sample output:
foo was indeed a char_wrapper
bar was indeed a short_wrapper
char_func()
short_func()
Thank you for your attention,
- Shao Miller
I'd like to offer some code which some of you might find interesting.
In the code, the func() macro effectively expands to a function which
depends on the type of the argument to the macro. This is useful for
when you wish to treat identifiers differently based on the identified
type. The function can be any function type, returning any type.
Requirements are:
- A "wrapper" type for any type you are interested in using with this
macro
- The wrapper type has a sizeof() being greater than or equal to
sizeof(char*)
- The undefined behaviour due to the "magic" where pointer arithmetic
jumps from one array object to another, dis-joint array object, even
though there are objects of the same type within the latter array
object
I am interested in:
- If anyone can identify an implementation which produces results
different than those found in the demonstration below, or at
http://codepad.org/Cf5zh5xS
- If anyone has any feedback about a "better way" to produce a macro
with similar functionality
The following demonstration can be compiled with 'gcc -ansi -pedantic -
Werror'.
-----
/*
* (C) Shao Miller, 2010
*
* Translation-time type information.
* At the cost of each wrapper type being >= sizeof(char*)
*/
#include <stddef.h>
#include <stdio.h>
enum types {
types_none,
types_char,
types_short,
types_int,
types_long,
types_total
};
union char_wrapper;
typedef char (*char_func_type)(union char_wrapper *this);
union short_wrapper;
typedef short (*short_func_type)(union short_wrapper *this);
/* etc. */
union char_wrapper {
char value;
char (*type)[types_char];
char_func_type func[1];
};
union short_wrapper {
short value;
char (*type)[types_short];
short_func_type func[1];
};
/* etc. */
/* This matches char_func_type */
char char_func(union char_wrapper *this) {
puts("char_func()");
return this->value;
}
/* This matches short_func_type */
short short_func(union short_wrapper *this) {
puts("short_func()");
return this->value;
}
/* etc. */
union any_func {
char_func_type char_func;
short_func_type short_func;
/* etc. */
};
union any_func funcs[types_total];
void init_funcs(void) {
funcs[types_char].char_func = char_func;
funcs[types_short].short_func = short_func;
/* etc. */
}
#define func(x) \
\
(*(x.func - ((char**)x.func - (char**)funcs) + sizeof(*x.type)))(&x)
int main(void) {
union char_wrapper foo;
char foo_test;
union short_wrapper bar;
short bar_test;
init_funcs();
if (sizeof(*foo.type) == types_char) {
puts("foo was indeed a char_wrapper");
}
if (sizeof(*bar.type) == types_short) {
puts("bar was indeed a short_wrapper");
}
foo_test = func(foo);
bar_test = func(bar);
return 0;
}
-----
Sample output:
foo was indeed a char_wrapper
bar was indeed a short_wrapper
char_func()
short_func()
Thank you for your attention,
- Shao Miller