C macro to assign a value - c

I have a struct of the form:
struct foo {
bool has_value;
int value;
}
I want to create a macro, which can be used to assign value as follows:
ASSIGN(foo) = 0;
or
ASSIGN(foo) += 5;
when the macro is:
#define ASSIGN(s) \
s->has_value = true; s->value
However, the macro is not if safe. In the example below if will "eat" the first part of the ASSIGN macro.
if (cond)
ASSIGN(foo) += 5;
Any proposal on how to make ASSIGN if safe?

Use a comma operator, and throw in parens for good measure.
#define ASSIGN(s) \
((s)->has_value = true), (s)->value
In an if-statement it would expand to:
if (cond)
((foo)->has_value = true), (foo)->value += 5;
However, macros in this usage are a very bad idea.
You can almost always come up with abusive code that will break your macro.
Even if it works, it will confuse future programmers who may read your code.
Here is one bad way this macro will break:
ASSIGN(foo) = M_PI;
printf("Sin of PI/2 = %f\n", sin(ASSIGN(foo) *= 0.5));
You might expect that to print 1.
It probably won't even compile.

Any proposal on how to make ASSIGN if safe?
You cannot, in general, do this. You should not use macros for an lvalue. It's a terrible idea, and it will most probably lead to crazy and impossible to find bugs.
This really seems like an XY problem. In your case, as I understand, you want to create a macro to simplify an expression that should be done over and over multiple times in your code.
Instead of using a simple one-argument macro, you can define a macro with two arguments. This way, it will be more compatible with the rest of your code, while still achieving the same result, using a more consistent semantic, which is also "if-safe".
Here it is (I'm calling it ASSIGN_FOO just to distinguish it from yours):
#define ASSIGN_FOO(x, v) do { (x)->has_value = true; (x)->value = v; } while (0)
struct foo var;
ASSIGN_FOO(var, 123);
If you're wondering about that do { ... } while (0), have a look here.
In case you want the macro to return the assigned value though (like you would expect from a normal assignment), this is not a good option.
Instead of using a macro, you can define an inline function, declaring it with __attribute__ ((always_inline)). This way, the compiler integrates the function's code directly into the caller, and the function will act exactly as a macro when the program is compiled, except that it is now more powerful as it can be used in more contexts.
inline int __attribute__ ((always_inline)) assign_foo(struct foo *x, int value) {
x->has_value = true;
x->value = value;
return x->value;
}
struct foo var;
assign_foo(var, 123);
In addition to this, it doesn't make much sense to use the macro you defined when updating the value in your struct, as it can easily lead to unwanted undefined behavior, like the following:
struct foo var;
ASSIGN(var) += 5;
Which expands to:
var->has_value = true; var->value += 5; // Undefined behavior, var->value used uninitialized!
The solution here is:
If you already know that the value is present, it doesn't make sense to re-assign has_value = true, you can just do the increment directly:
var->value += 10;
If you don't know if the value is present, use a function to do it safely instead:
inline int __attribute__ ((always_inline)) increment_foo(struct foo *x, int value) {
if (!x->has_value) {
x->has_value = true;
x->value = value;
} else {
x->value += value;
}
return x->value;
}
increment_foo(var, 10);
Comparison:
struct foo x;
printf("%d\n", ASSIGN(x) = 3); // Compilation error.
printf("%d\n", ASSIGN_FOO(x, 3); // Compilation error.
printf("%d\n", assign_foo(x, 3)); // No problem.
struct foo y;
printf("%d\n", ASSIGN(y) += 3); // Compilation error.
ASSIGN(y) += 3; printf("%d\n", y->value); // Undefined behavior.
printf("%d\n", increment_foo(y, 3)); // No problem.

Such syntax-breaking macros are usually a bad idea but you can do it with
#define ASSIGN(s) ((s).has_value=1,&(s))->value
if you want it to take an lvalue or
#define ASSIGN(sp) ((sp)->has_value=1,(sp))->value
if you want it to take a pointer.
Working example (https://godbolt.org/z/fHAGRa):
#include <stdbool.h>
#include <stdio.h>
struct foo {
bool has_value;
int value;
};
#define ASSIGN(s) ((s).has_value=1,&(s))->value
int main()
{
struct foo x;
ASSIGN(x) = 21;
printf("%d\n", ASSIGN(x) *= 2 ); //prints 42
return ASSIGN(x); //returns the last value (42)
}
It doesn't protect from double-evaluation—for that you'd need the expression statement extension or a helper inline function such as
static inline struct foo *set_has_value_return_ptr(struct foo *X){
return X->has_value=1, X;
}
#define ASSIGN(s) (set_has_value_return_ptr(&(s)))->value
Explanation:
The naive ((s).has_value=1,(s).value) or ((s).has_value=1,(s)).value wouldn't work because of lvalue to rvalue conversion done by the comma operator, but ((s).has_value=1,&(s))->value or (*((s).has_value=1,&(s))).value will because pointer dereferencing (*) and -> always yield lvalues regardless of whether their pointer argument was an lvalue or an rvalue.

Related

A homework is about use macro

This questions is about my homework.
This topic is need to use like:
#define GENERIC_MAX(type)\
type type##_max(type x, type y)\
{\
return x > y ? x : y;\
}
The content of the question is to make this code run normally:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
The result of the operation is like this:
i=5.2000
j=3
And this code is my current progress, but there are have problems:
#include <stdio.h>
#define printname(n) printf(#n);
#define GenerateShowValueFunc(type)\
type showValue_##type(type x)\
{\
printname(x);\
printf("=%d\n", x);\
return 0;\
}
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
I don’t know how to make the output change with the type, and I don’t know how to display the name of the variable. OAO
This original task description:
Please refer to ShowValue.c below:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Through [GenerateShowValueFunc(double)] and [GenerateShowValueFunc(int)] these two lines macro call, can help us to generated as [showValue_double( double )] and [showValue_int( int )] function, And in main() function called. The execution result of this program is as follows:
i=5.2000
j=3
Please insert the code that defines GenerateShowValueFunc macro into the appropriate place in the ShowValue.c program, so that this program can compile and run smoothly.
A quick & dirty solution would be:
type showValue_##type(type x)\
{\
const char* double_fmt = "=%f\n";\
const char* int_fmt = "=%d\n";\
printname(x);\
printf(type##_fmt, x);\
return 0;\
}
The compiler will optimize out the variable that isn't used, so it won't affect performance. But it might yield warnings "variable not used". You can add null statements like (void)double_fmt; to silence it.
Anyway, this is all very brittle and bug-prone, it was never recommended practice to write macros like these. And it is not how you do generic programming in modern C. You can teach your teacher how, by showing them the following example:
#include <stdio.h>
void double_show (double d)
{
printf("%f\n", d);
}
void int_show (int i)
{
printf("%d\n", i);
}
#define show(x) _Generic((x),\
double: double_show, \
int: int_show) (x) // the x here is the parameter passed to the function
int main()
{
double i = 5.2;
int j = 3;
show(i);
show(j);
}
This uses the modern C11/C17 standard _Generic keyword, which can check for types at compile-time. The macro picks the appropriate function to call and it is type safe. The caller doesn't need to worry which "show" function to call nor that they pass the correct type.
Without changing the shown C-code (i.e. only doing macros), which I consider a requirement, the following code has the required output:
#include <stdio.h>
#define showValue_double(input) \
showValueFunc_double(#input"=%.4f\n" , input)
#define showValue_int(input) \
showValueFunc_int(#input"=%d\n" , input)
#define GenerateShowValueFunc(type) \
void showValueFunc_##type(const char format[], type input)\
{\
printf(format, input); \
}
/* ... macro magic above; */
/* unchangeable code below ... */
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Output:
i=5.2000
j=3
Note that I created something of a lookup-table for type-specific format specifiers. I.e. for each type to be supported you need to add a macro #define showValue_ .... This is also needed to get the name of the variable into the output.
This uses the fact that two "strings" are concatenated by C compilers, i.e. "A""B" is the same as "AB". Where "A" is the result of #input.
The rest, i.e. the required function definition is very similar to the teacher-provided example, using the ## operator.
Note, this is if the variable name has to correctly be mentioned in the output.
With out the i = things would be easier and would more elegantly use the generated functions WITHOUT having the called showValue_double(i); be explicit macros. I.e. the functions generated are 1:1 what is called from main(). I think that might be what is really asked. Let me know if you want that version.

`_Generic` with a type as output

_Generic can select between different statements based on the type of the variable passed, however (as somewhat expected) it fails if these statements contain type names themselves. As an example:
#define PROMOTE(var) \
_Generic((var), \
char: int);
int main() {
char c;
PROMOTE(c) i = 0;
return 0;
}
One might expect the above code to work, with the line using PROMOTE evaluating to "int i = 0", but alas, it does not compile. I tried some roundabout ways to write the type (int), such as with a macro (#define TYPE_int int) or a typedef (typedef int TYPE_int), but to no avail. This is most probably intended (or purposefully undefined) behavior, but I'm still interested in the possibility, even if it requires some C wizardry.
In light of that, how can one make _Generic output a type?
Note: Solutions should rely only on standard C (i.e. no compiler specific constructs).
The closest thing I can imagine is combination of _Generic, compound literals and typeof extension available in popular compilers like GCC and CLANG.
#include <stdio.h>
struct SomeStruct { int x; };
#define PROMOTE(X) typeof(_Generic((X){0}, char: (int){0}, int: (float){0}, float: (struct SomeStruct){0}))
int main() {
PROMOTE(char) a = 1;
PROMOTE(int) b = 2.0f;
PROMOTE(float) c = { .x = 42 };
printf("%d\n", a);
printf("%f\n", b);
printf("%d\n", c.x);
return 0;
}
prints
1
2.000000
42
Unfortunately, This is not standard C.

Conversion to non-scalar error inside macro in C

I have the following test code in C:
#include <stdio.h>
#include <stdlib.h>
typedef struct test {
int a;
int b;
} test_t;
#define test_init(test, a) \
test = (test_t)calloc(1, sizeof(test_t)); \
(test)->a = a; \
(test)->b = (test)->a + 1; \
int main()
{
test_t test;
int a = 5;
test_init(&test, a);
return 0;
}
But it throws the following error:
error: conversion to non-scalar type requested
Why exactly dos this happen? Please note that the discussion is not here whether to use an actual function or a macro. Let's just assume we are interested in macros. Why is the above error thrown, and what is the proper way to handle it?
Recall that function-like macros perform a direct substitution of their parameters. That means this:
test_init(&test, a);
Gets converted by the preprocessor into:
&test = (test_t)calloc(1, sizeof(test_t));
(&test)->a = a;
(&test)->b = (&test)->a + 1;
Note that in the first line you're attempting to assign something to &test. The result of the & operator does not result in an lvalue. That means you can't assign something to &test because it doesn't represent something you can assign to.
To fix this, you need to declare test in main as a pointer:
test_t *test;
int a = 5;
test_init(test, a);
Or, if you expect the macro to be passed an instance of type test_t, you don't need the call to calloc:
#define test_init(test, a) \
(test).a = a; \
(test).b = (test).a + 1; \

c function chaining possible?

I was wondering if it is possible in C (89/90) to chain function calls, and where it is defined in the C spec. I assume this isn't possible since a google search reveals no mention of it.
I thought of this because of a related conversation with a friend of mine where he told me that given a function returning a struct, you cannot perform any operations on said struct within the same statement; instead, you have to assign the result of the function to a variable, and then manipulate the struct via the variable instead of directly from the function result itself. This leads me to believe that you can't chain functions either, but I can't seem to find these limitations discussed in the spec.
Edit : Sorry, I should have been specific on the return value. Assuming the function returns a function pointer, is it possible to dereference and call the result within the same statement, in fluent fashion?
For example, assuming getFunc returns a function pointer :
(*getFunc(getFuncParam))(otherFuncParam)
Or in the struct case, assuming a struct with an int member called count:
funcReturnsStruct(param).count++
Here's what function chaining looks like in C:
post_process(process(pre_process(data)));
Obviously, your friend is wrong. As long as the functions cooperate by accepting and returning the same type of value you can chain the calls all you like.
Contrast this with something like
data.pre_process().process().post_process();
The big difference is that in C (which has no encapsulation, hence no classes) functions have center stage while in more modern OO languages it's objects that get more attention.
Update: Sure it's possible to chain no matter what each function might return. For example:
int increase(int x) {
return x + 1;
}
typedef int (*increase_fp)(int);
increase_fp get_increase() {
return increase;
}
int main(void) {
printf("%d", get_increase()(1));
return 0;
}
See it in action.
a friend of mine where he told me that given a function returning a struct, you cannot perform any operations on said struct within the same statement
Your friend is correct in the sense that the return value of a function cannot be the target of an assignment (it's not an lvalue). IOW, you can't do something like
int foo(void) { int x = 5; return x; }
...
foo() = 6;
However, if the return type of a function is a struct or a union, you can apply the component selection operator to the return value, such as
int x = foo().memb;
Similarly, if the return type of the function is a pointer to a struct or a union, you can write
int x = foo()->memb;
And if the return value is a pointer to another function, you can call that other function like so:
int bar(int x) { ... }
int (*foo)(int x) { return bar; }
int x = foo(x)(y); // or (*foo(x))(y) -- the result of foo(x) is
// called with the argument y
although anyone who has to maintain or debug your code may beat you severely for it.
What you cannot do is something like
foo().memb= ...;
foo()->memb = ...;
which wouldn't make sense anyway, because the lifetime of the value returned by foo ends when the statement ends - you wouldn't be able to retrieve that modified value.
Your friend is wrong.
If we have:
struct Point3
{
float x, y, z;
};
const Point3 * point3_get_origin(void);
then you can certainly do:
printf("the origin's y coordinate is %f\n", point3_get_origin()->y);
The function returns a value of the given type, so the call of the function can be used wherever such a value is needed in an expression.
Do you mean something like this?
typedef void (*CALLBACK)(void);
CALLBACK getCallback();
void test()
{
getCallback()();
}
It compiles with no warning in GCC 4.6.1 (default std).
There's a much faster and easier way to answer this than posting here: try it.
#include <stdio.h>
struct s {
int a;
} s;
struct s * getS() {
s.a = 13;
return &s;
}
int main(int argc, char * const argv[]) {
printf("%d\n", getS()->a);
return 0;
}
% gcc test.c -o test -Wall -pedantic
% ./test
13
%
Not so much as a pedantic warning. Expected output. Looks like it's perfectly fine. However, as has been pointed out, it would be better to store the return value and check for errors.

Can a C macro contain temporary variables?

I have a function that I need to macro'ize. The function contains temp variables and I can't remember if there are any rules about use of temporary variables in macro substitutions.
long fooAlloc(struct foo *f, long size)
{
long i1, i2;
double *data[7];
/* do something */
return 42;
}
MACRO Form:
#define ALLOC_FOO(f, size) \
{\
long i1, i2;\
double *data[7];\
\
/* do something */ \
}
Is this ok? (i.e. no nasty side effect - other than the usual ones : not "type safe" etc). BTW, I know "macros are evil" - I simply have to use it in this case - not much choice.
There are only two conditions under which it works in any "reasonable" way.
The macro doesn't have a return statement. You can use the do while trick.
#define macro(x) do { int y = x; func(&y); } while (0)
You only target GCC.
#define min(x,y) ({ int _x = (x), _y = (y); _x < _y ? _x : _y; })
It would help if you explain why you have to use a macro (does your office have "macro mondays" or something?). Otherwise we can't really help.
C macros are only (relatively simple) textual substitutions.
So the question you are maybe asking is: can I create blocks (also called compound statements) in a function like in the example below?
void foo(void)
{
int a = 42;
{
int b = 42;
{
int c = 42;
}
}
}
and the answer is yes.
Now as #DietrichEpp mentioned it in his answer, if the macro is a compound statement like in your example, it is a good practice to enclose the macro statements with do { ... } while (0) rather than just { ... }. The link below explains what situation the do { ... } while (0) in a macro tries to prevent:
http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html
Also when you write a function-like macro always ask yourself if you have a real advantage of doing so because most often writing a function instead is better.
First, I strongly recommend inline functions. There are very few things macros can do and they can't, and they're much more likely to do what you expect.
One pitfall of macros, which I didn't see in other answers, is shadowing of variable names.
Suppose you defined:
#define A(x) { int temp = x*2; printf("%d\n", temp); }
And someone used it this way:
int temp = 3;
A(temp);
After preprocessing, the code is:
int temp = 3;
{ int temp = temp*2; printf("%d\n", temp); }
This doesn't work, because the internal temp shadows the external.
The common solution is to call the variable __temp, assuming nobody will define a variable using this name (which is a strange assumption, given that you just did it).
This is mostly OK, except that macros are usually enclosed with do { ... } while(0) (take a look at this question for explanations):
#define ALLOC_FOO(f, size) \
do { \
long i1, i2;\
double *data[7];\
/* do something */ \
} while(0)
Also, as far as your original fooAlloc function returns long you have to change your macro to store the result somehow else. Or, if you use GCC, you can try compound statement extension:
#define ALLOC_FOO(f, size) \
({ \
long i1, i2;\
double *data[7];\
/* do something */ \
result; \
})
Finally you should care of possible side effects of expanding macro argument. The usual pattern is defining a temporary variable for each argument inside a block and using them instead:
#define ALLOC_FOO(f, size) \
({ \
typeof(f) _f = (f);\
typeof(size) _size = (size);\
long i1, i2;\
double *data[7];\
/* do something */ \
result; \
})
Eldar's answer shows you most of the pitfalls of macro programming and some useful (but non standard) gcc extension.
If you want to stick to the standard, a combination of macros (for genericity) and inline functions (for the local variables) can be useful.
inline
long fooAlloc(void *f, size_t size)
{
size_t i1, i2;
double *data[7];
/* do something */
return 42;
}
#define ALLOC_FOO(T) fooAlloc(malloc(sizeof(T)), sizeof(T))
In such a case using sizeof only evaluates the expression for the type at compile time and not for its value, so this wouldn't evaluate F twice.
BTW, "sizes" should usually be typed with size_t and not with long or similar.
Edit: As to Jonathan's question about inline functions, I've written up something about the inline model of C99, here.
Yes it should work as you use a block structure and the temp variables are declared in the inner scope of this block.
Note the last \ after the } is redundant.
A not perfect solution: (does not work with recursive macros, for example multiple loops inside each other)
#define JOIN_(X,Y) X##Y
#define JOIN(X,Y) JOIN_(X,Y)
#define TMP JOIN(tmp,__LINE__)
#define switch(x,y) int TMP = x; x=y;y=TMP
int main(){
int x = 5,y=6;
switch(x,y);
switch(x,y);
}
will become after running the preprocessor:
int main(){
int x=5,y=6;
int tmp9 = x; x=y; y=tmp9;
int tmp10 = x; x=y; y=tmp10;
}
They can. They often shouldn't.
Why does this function need to be a macro? Could you inline it instead?
If you're using c++ use inline, or use -o3 with gcc it will inline all functions for you.
I still don't understand why you need to macroize this function.

Resources