Expand string into keyword - c

I am writing a program which was a struct with a need to store information on what type it's holding. The data is represented inside the the struct as a pointer to void. A short example of what I mean:
#include <stdio.h>
struct foo {
void *data;
char *type;
};
int main() {
struct foo bar = {{'a', 'b', 'c'}, "char"};
printf("%s\n", (STRING_TO_TYPE(bar.type))bar.data);
return 0;
}
I need an implementation of the STRING_TO_TYPE macro that will replace "char" with char. All of this can be evaluated at compile time for the needs of my program.
What I want to do is hold an object of any type, so using an enum or checking for string equality will not work.

Short answer: it is not possible. Not your way. Macros can produce tokens (keywords, if you like), but cannot convert strings to them.
That said, if the thing you are after is really
Being able to define a struct with a "type" of its void * somewhere in the code,
Being able to access that type as a keyword from the struct's name,
then you will most likely end up with typeof. It is a GNU extension, so it will only work in GCC, but it works.
In the example code here, you define your struct of a certain "type" with the MYSTRUCT macro and get the type using the TYPE macro. The __COUNTER__ predefined macro prevents type redefining (each struct is its own type, see gcc -E) and three macro levels for MYSTRUCT are there for proper stringification of it.
#include <stdio.h>
#define TYPE(x) typeof(x.type)
#define MYSTRUCT(name, type) MYSTRUCT_INTER(name, type, __COUNTER__)
#define MYSTRUCT_INTER(name, type, counter) MYSTRUCT_RAW(name, type, counter)
#define MYSTRUCT_RAW(xName, xType, xCounter) \
struct mystruct_## xCounter { \
void * data; \
xType type; \
} xName
int main(void) {
MYSTRUCT(foo, int);
foo.data = (void *)42;
TYPE(foo) tmp = foo.data; /* <-- Here, tmp is an int */
printf("%d\n", tmp);
MYSTRUCT(bar, int*);
bar.data = &tmp;
TYPE(bar) tmp2 = bar.data; /* <-- Here, tmp2 is an int* */
printf("%p\n", tmp2);
MYSTRUCT(baz, char*);
baz.data = "Hello world";
printf("%s\n", (TYPE(baz))baz.data);
/* ^Expands to (char *) baz.data */
}
Note that I still need to know the struct's "type" to determine printf()'s format code, but solving this was not asked.
Don't forget to compile with -std=gnu** (you need it for typeof)

Related

In C, can a primitive be passed to a function, which is looking for a user-defined datatype as input, if a casting/promotion rule is defined?

Suppose we have a function like this:
void WonderfulFunction(float a)
Clearly, we can pass an int to wonderful_function and the C-compiler will promote the int to a float.
However, what about user-defined data types? Suppose we use a typedef statement to give a name/alias to a struct. Is there some way to define a promotion-rule, casting function, or constructor which will automatically convert a primitive to ADT (abstract data type)? I realize this can be done in C++, but this needs to be in C.
We want something like the following code to compile correctly:
// #include <niffty_promoter_castOperator_thing.h>
struct HappyStruct {
int happy_int;
};
typedef struct HappyStruct HappyStruct;
/* prototype */
void AnotherWonderfulFunction(HappyStruct hs)
int main( ) {
int a = 12345;
AnotherWonderfulFunction(a);
// A caster/promoter included in the
// header file specifies how to
// construct a HappyStruct from an int
return 0;
}
void AnotherWonderfulFunction(HappyStruct hs) {
// do stuff;
}
This is "possible" with generic selection (YMMV); this described here is the closest you can get in C11. (In C99, C89 this is not possible at all). Here, AnotherWonderfulFunction(X) is a macro that will expand to (AnotherWonderfulFunction)(AsHappy(X)); the parentheses ensure that the macro is not recursively expanded.
AsHappy(X) is a macro that uses generic selection to choose one from 2 utility functions - HappyAsIs takes a struct HappyStruct as a parameter and returns it as-is, whereas HappyFromInt expects an int argument, and will return it wrapped in a struct. It needs to be done using utility functions, because at least GCC does check the language constraints for other branches, even though they're not evaluated. The original X is then passed to the selected function as an argument.
#include <stdio.h>
struct HappyStruct {
int happy_int;
};
void AnotherWonderfulFunction(struct HappyStruct hs) {
printf("AnotherWonderfulFunction called with hs.happy_int = %d\n", hs.happy_int);
}
struct HappyStruct HappyAsIs(struct HappyStruct s) {
return s;
}
struct HappyStruct HappyFromInt(int val) {
return (struct HappyStruct){ val };
}
#define AsHappy(X) \
_Generic((X), \
struct HappyStruct: HappyAsIs, \
default: HappyFromInt \
)(X)
#define AnotherWonderfulFunction(X) (AnotherWonderfulFunction)(AsHappy(X))
int main(void) {
int a = 42;
float b = 65536.5;
struct HappyStruct c = { 123 };
AnotherWonderfulFunction(a);
AnotherWonderfulFunction(b);
AnotherWonderfulFunction(c);
}
and running the program produces:
% ./a.out
AnotherWonderfulFunction called with hs.happy_int = 42
AnotherWonderfulFunction called with hs.happy_int = 65536
AnotherWonderfulFunction called with hs.happy_int = 123
However, the magic disappears as soon as you take a pointer to a function;
void (*fp)(struct HappyStruct) = AnotherWonderfulFunction;
now of course fp cannot work that way because it is not a macro.
... until you make it one ...
#define fp(X) (fp)(AsHappy(X))
All this is somewhat useless, since C11 supports compound literals:
AnotherWonderfulFunction((struct HappyStruct){ 42 });
so it is of limited use - lots of black magic to save a few keystrokes.
For cases where you only care about the binary representation (i.e., not in the int-to-float case), you can use GCC's __attribute__((transparent_union))

C structure as a data type

I want to be able to do something like this:
typedef struct
{
char* c_str;
} string;
string s = "hello";
Is it possible to do that in any way?
I know that it is possible to do this:
typedef struct
{
char* c_str;
} string;
string s = { "hello" };
But I do not like the curly brackets when it is only one member variable.
You could use a typedef instead of a struct:
typedef char* string;
string s = "hello";
But then const string would make the pointer const, and not the pointed-to data. So const string s is equivalent to char* const s. A solution may be to define an additional type for const strings:
typedef char* string;
typedef const char* const_string;
For the original struct, the same is true. (C++ has the same "problem", which is why it has iterator and const_iterator in its container types.)
An advantage of a typedef for a pointer type is that you can type
string s1, s2, s3;
instead of
char *s1, *s2, *s3;
In C, it is not possible, but you can do it in C++ if you add constructor that takes one appropriate parameter. Compiler will do the rest. You can mark the constructor as explicit if you want to avoid this implicit conversion behaviour.
In C++:
struct string {
char * m_c_str;
/* explicit */ string(char* c_str) : m_c_str(c_str) { }
};
int main(int argc, char * argv[]) {
string s = "hello";
return 0;
}
Is it possible to do that in any way?
No. It is not possible to do it with struct or union. Para 16 of section 6.7.9 states that
[...] the initializer for an object that has aggregate or union type shall be a braceenclosed list of initializers for the elements or named members.
There is another way to do the same with different data type as explained in this answer.
Not sure if this is actually canonical and fits the C Standards as Microsoft Visual Studio has the reputation of being a bit loose in interpreting the standard, however here is an approach that compiles and works when viewed in the debugger of Visual Studio 2005.
Though if you do not like curly brace initializers you probably would not care for a macro either.
typedef struct {
char *c_str;
} String;
// following macro assigns the string to the struct member and uses the
// comma operator to make the statement return the original struct variable.
#define xString(x, y) ((x).c_str = (y), (x))
void jjj (void)
{
String b = xString(b,"hello");
}
I was able to define multiple variables at a time so multiple variable definitions on the same line compiles as in:
String b = xString(b,"hello"), c = xString(c,"Jello");
It might be that you would want to have a macro that would do the entire statement in a kind of functional language looking construct though there could only be one per statement so multiple on the same line would require semicolons to separate into individual definition statements.
#define xString(x,y) String x = (x.c_str = (y), x)
and it would be used as
void jjj (void)
{
xString(myStruct, "hello");
int j = 2;
// .. do stuff
}
or you could just use
#define xString(x,y) String x = {y}
Initializer list really does seem to be the best approach if you want a struct for some reason to allow compile time argument checking on a specific type of char *.
Where it gets kind of awesome is when you do something like the following to initialize multiple struct members at the time the struct variable is defined.
typedef struct {
int len;
char *c_str;
} String2;
#define yString(x,y) x = (x.c_str = (y), x.len = strlen(y), x)
void jjj (void)
{
String2 b2 = yString(b2,"Hello");
int j = 2;
// .. do stuff
}
Being curious I tried another variation that looks like the following. This does move away from the specific question and more into what are possibilities of following this approach down the rabbit hole. Using the same struct with a different macro that allows you to specify a struct member to initialize along with the value.
typedef struct {
int len;
char *c_str;
} String2;
#define zString(x,y,a,b) x=(x.c_str=(y),x.a=(b),x)
void jjj (void)
{
String2 b3 = zString(b3,"Hello",len,72);
// ... do stuff
}

Complete encapsulation without malloc

I was experimenting with C11 and VLAs, trying to declare a struct variable on the stack with only an incomplete declaration. The objective is to provide a mechanism to create a variable of some struct type without showing the internals (like the PIMPL idiom) but without the need to create the variable on the heap and return a pointer to it. Also, if the struct layout changes, I don't want to recompile every file that uses the struct.
I have managed to program the following:
private.h:
#ifndef PRIVATE_H_
#define PRIVATE_H_
typedef struct A{
int value;
}A;
#endif /* PRIVATE_H_ */
public.h:
#ifndef PUBLIC_H_
#define PUBLIC_H_
typedef struct A A;
size_t A_getSizeOf(void);
void A_setValue(A * a, int value);
void A_printValue(A * a);
#endif /* PUBLIC_H_ */
implementation.c:
#include "private.h"
#include "stdio.h"
size_t A_getSizeOf(void)
{
return sizeof(A);
}
void A_setValue(A * a, int value)
{
a->value = value;
}
void A_printValue(A * a)
{
printf("%d\n", a->value);
}
main.c:
#include <stdalign.h>
#include <stddef.h>
#include "public.h"
#define createOnStack(type, variable) \
alignas(max_align_t) char variable ## _stack[type ## _getSizeOf()]; \
type * variable = (type *)&variable ## _stack
int main(int argc, char *argv[]) {
createOnStack(A, var);
A_setValue(var, 5335);
A_printValue(var);
}
I have tested this code and it seems to work. However I'm not sure if I'm overlooking something (like aliasing, alignment or something like that) that could be dangerous or unportable, or could hurt performance. Also I want to know if there are better (portable) solutions to this problem in C.
This of course violates the effective typing rules (aka strict aliasing) because the C language does not allow an object of tye char [] to be accessed through a pointer that does not have that type (or a compatible one).
You could disable strict aliasing analysis via compiler flags like -fno-strict-aliasing or attributes like
#ifdef __GNUC__
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
(thanks go to R.. for pointing out the latter), but even if you do not do so, in practice everything should work just fine as long as you only ever use the variable's proper name to initialize the typed pointer.
Personally, I'd simplify your declarations to something along the lines of
#define stackbuffer(NAME, SIZE) \
_Alignas (max_align_t) char NAME[SIZE]
typedef struct Foo Foo;
extern const size_t SIZEOF_FOO;
stackbuffer(buffer, SIZEOF_FOO);
Foo *foo = (void *)buffer;
The alternative would be using the non-standard alloca(), but that 'function' comes with its own set of issues.
I am considering adopting a strategy similar to the following to solve essentially the same problem. Perhaps it will be of interest despite being a year late.
I wish to prevent clients of a struct from accessing the fields directly, in order to make it easier to reason about their state and easier to write reliable design contracts. I'd also prefer to avoid allocating small structures on the heap. But I can't afford a C11 public interface - much of the joy of C is that almost any code knows how to talk to C89.
To that end, consider the adequate application code:
#include "opaque.h"
int main(void)
{
opaque on_the_stack = create_opaque(42,3.14); // constructor
print_opaque(&on_the_stack);
delete_opaque(&on_the_stack); // destructor
return 0;
}
The opaque header is fairly nasty, but not completely absurd. Providing both create and delete functions is mostly for the sake of consistency with structs where calling the destructor actually matters.
/* opaque.h */
#ifndef OPAQUE_H
#define OPAQUE_H
/* max_align_t is not reliably available in stddef, esp. in c89 */
typedef union
{
int foo;
long long _longlong;
unsigned long long _ulonglong;
double _double;
void * _voidptr;
void (*_voidfuncptr)(void);
/* I believe the above types are sufficient */
} alignment_hack;
#define sizeof_opaque 16 /* Tedious to keep up to date */
typedef struct
{
union
{
char state [sizeof_opaque];
alignment_hack hack;
} private;
} opaque;
#undef sizeof_opaque /* minimise the scope of the macro */
void print_opaque(opaque * o);
opaque create_opaque(int foo, double bar);
void delete_opaque(opaque *);
#endif
Finally an implementation, which is welcome to use C11 as it's not the interface. _Static_assert(alignof...) is particularly reassuring. Several layers of static functions are used to indicate the obvious refinement of generating the wrap/unwrap layers. Pretty much the entire mess is amenable to code gen.
#include "opaque.h"
#include <stdalign.h>
#include <stdio.h>
typedef struct
{
int foo;
double bar;
} opaque_impl;
/* Zero tolerance approach to letting the sizes drift */
_Static_assert(sizeof (opaque) == sizeof (opaque_impl), "Opaque size incorrect");
_Static_assert(alignof (opaque) == alignof (opaque_impl), "Opaque alignment incorrect");
static void print_opaque_impl(opaque_impl *o)
{
printf("Foo = %d and Bar = %g\n",o->foo,o->bar);
}
static void create_opaque_impl(opaque_impl * o, int foo, double bar)
{
o->foo = foo;
o->bar = bar;
}
static void create_opaque_hack(opaque * o, int foo, double bar)
{
opaque_impl * ptr = (opaque_impl*)o;
create_opaque_impl(ptr,foo,bar);
}
static void delete_opaque_impl(opaque_impl *o)
{
o->foo = 0;
o->bar = 0;
}
static void delete_opaque_hack(opaque * o)
{
opaque_impl * ptr = (opaque_impl*)o;
delete_opaque_impl(ptr);
}
void print_opaque(opaque * o)
{
return print_opaque_impl((opaque_impl*)o);
}
opaque create_opaque(int foo, double bar)
{
opaque tmp;
unsigned int i;
/* Useful to zero out padding */
for (i=0; i < sizeof (opaque_impl); i++)
{
tmp.private.state[i] = 0;
}
create_opaque_hack(&tmp,foo,bar);
return tmp;
}
void delete_opaque(opaque *o)
{
delete_opaque_hack(o);
}
The drawbacks I can see myself:
Changing the size define manually would be irritating
The casting should hinder optimisation (I haven't checked this yet)
This may violate strict pointer aliasing. Need to re-read the spec.
I am concerned about accidentally invoking undefined behaviour. I would also be interested in general feedback on the above, or whether it looks like a credible alternative to the inventive VLA technique in the question.

Comparing Types Of Names In C

I'm trying to write a macro in C (alas, not C++) in a way to trap certain errors, in particular if I pass a name of the wrong type.
For example, with
typedef int APLNELM;
typedef int APLRANK;
#define IsScalar(a) ((a) == 0)
APLNELM AplNelm = 0;
APLRANK AplRank = 0;
Calling IsScalar (AplRank) is correct because Scalar is a Rank concept, but IsScalar (AplNelm) is wrong because Scalar is not a # elements concept.
Can some clever person find a way to write the IsScalar macro such that it checks the type of the name passed to it to ensure that it is of type APLRANK? Feel free to rewrite the original example in any equivalent way if that provides a solution.
If these are the only two types that will ever be passed into the isScalar macro, then you could do something like this:
#include <stdio.h>
struct APLNELM {
int nelm;
char a[1];
};
struct APLRANK {
int rank;
char a[2];
};
#define isScalar(b) (sizeof b.a == 2)
int main(void) {
// your code goes here
struct APLNELM temp1;
struct APLRANK temp2;
printf("%d\n", isScalar(temp1));
printf("%d\n", isScalar(temp2));
return 0;
}
The output of this code is
0
1
This will work, but I highly suggest you don't use it as it wouldn't be super maintainable:
typedef int APLNELM;
typedef int APLRANK;
typedef unsigned int TYPETRAITS;
#define TRAIT_SCALAR 0x1
#define TYPETRAITS_APLNELM TRAIT_SCALAR /*whatever else you want, up to 32 traits*/
#define TYPETRAITS_APLRANK 0/*whatever else you want, up to 32 traits*/
#define GET_TYPE_TRAITS(X) TYPETRAITS_##X
#define IS_SCALAR(X) (X & TRAIT_SCALAR)
#define IS_TYPE_SCALAR(X) IS_SCALAR(GET_TYPE_TRAITS(X))
int main()
{
const int aplnelm_traints = GET_TYPE_TRAITS(APLNELM);
const int aplrang_traints = GET_TYPE_TRAITS(APLRANK);
const bool is_aplnelm_scalar = IS_TYPE_SCALAR(APLNELM);
const bool is_aplrang_scalar = IS_TYPE_SCALAR(APLNELM);
}
I gived up with following code (requires GNU extensions: typeof and Statement Exprs):
#include <stdio.h>
typedef int APLNELM;
typedef int APLRANK;
#define IsScalar(a) \
({ \
/* Override typedefs in block scope */ \
typedef char APLNELM; \
typedef int APLRANK; \
/* Create variable with typeof(a) type; \
* then compare it by sizeof with APLNELM */ \
typeof(a) b; sizeof b == sizeof(APLNELM); \
})
int main(void)
{
APLNELM a = 5;
APLRANK b = 5;
printf("IsScalar: %d\n", IsScalar(a) ? 1 : 0);
printf("IsScalar: %d\n", IsScalar(b) ? 1 : 0);
return 0;
}
The thing is that typeof(a) is actually not replaced by APLNELM or APLRANK. C is not dynamic language, I agree that struct concept would be better suited for such differentiation.
If you want to define two integer types that are different, the straight typedef approach fails, because typedef creates synonyms for the same type, never creates new types.
There is a manner to create different integer types, but even in this case, there is no way to "detect" them through their values.
For example, observe this code:
enum myint1_e {min1 = -32767, max1 = 32767};
enum myint2_e {min2 = -32767, max2 = 32767};
typedef enum myint1_e integer1_t;
typedef enum myint2_e integer2_t;
integer1_t x1 = 0;
integer2_t x2 = 0;
Now, the two types enum myint1_t and enum myint2_t are different integer types.
See C11: 6.7.2.3.(par.5):
Two declarations of [...] enumerated types which are in different scopes or use different tags declare distinct types.
So, their typedef-ed versions are, too, different.
Thus, the variables x1 and x2 have different types.
The integer value 0 can be assigned to both variables.
Now, if you want to check that the type of a variable is the one that you want, you can try doing that:
#define VERIFY_INT1TYPE(a) ((integer1_t*)(0) == (&a))
But this method only offers a Warning message, and not the "comparisson with value false" that you expected.
Explanation: Although the integer types are, in some way, interchangeable in assignment operations, on the other hand their "pointer to" versions are always different types. Thus, a sentence like x1 == x2 has not any problem at all, but the comparisson of a value of two different pointer types will raise a warning message.
Remark: The expression (integer1_t*)(0) is the NULL pointer cast to type integer1_t*.
Example:
VERIFY_INT1TYPE(x2);
This example raise a warning message when I compiled with GCC.
One possibility is to wrap the integer in a one-field struct, to enforce strong typing. To avoid the final production code being suboptimal, compile twice with different macro definitions; once with structs to detect errors, once without structs for optimal code.
#ifdef STRONG_TYPING
#define TYPE(basetype, field) struct { basetype field; }
#define INITIALIZER(value) {(value)}
#define AS_BASETYPE(field, value) ((value).field)
#else
#define TYPE(basetype, field) basetype
#define INITIALIZER(value) (value)
#define AS_BASETYPE(field, value) (value)
#endif
typedef TYPE(int, alpnelm) APLNELM;
typedef TYPE(int, alprank) APLRANK;
#define IsScalar(a) (AS_BASETYPE(aplrank, a) == 0)
With STRONG_TYPING defined, IsScalar(SomeAplNelm) will give a compiler error. Without STRONG_TYPING, the overhead of structs will be completely gone. Naturally, all modules must to be compiled with the same definition before linking, or your executable is likely to crash.
In your program code, you will have to apply some discipline when it comes to using the macros. Declaration example:
APLNELM MyAplNelm1;
APLNELM MyAplNelm2 = INITIALIZER(0);
Assignment:
AS_BASETYPE(aplnelm, MyAplNelm1) = 0;
AS_BASETYPE(aplnelm, MyAplNelm2) = AS_BASETYPE(aplnelm, MyAplNelm1);
It is still allowed to exchange values between different 'strong' types; as long as you specify the correct type (name of the field in the struct) for each individual value.
AS_BASETYPE(aplnelm, MyAplNelm2) = AS_BASETYPE(aplrank, MyAplRank);
Please note you always need AS_BASETYPE to access a variable of one of the 'strong' types. This will make the code more verbose (please feel free to choose a shorter name for the macro), but there's nothing wrong with that. It's just a notion of metadata you are adding; it should actually improve maintainability.

Accessing a general structure member using a variable

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.

Resources