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; \
Related
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 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.
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.
I just found somewhere a code like :
#include"stdio.h"
typedef struct st
{
int num;
char c;
int abc;
} Str, *pStr;
#define MyStr(Dcn) Str(Dcn)
int main()
{
Str Str1;
MyStr(Dcn);
return 0;
}
Please tell what the #define line means here? As it is not giving any compilation problem. So if I use #define something to a "structure with parentheses" then what happens?
Here Dcn can be anything not with quotes. When I used a number instead it showed compilation error.
This defines an alias for Str. It is equivalent to
int main()
{
Str Str1;
Str(Dcn);
return 0;
}
Which simply declares a variable Dcn of type Str.
It's a function-like macro, it's expanded to the right-hand side with the arguments replaced.
A classical example is this, to compute max of two values:
#define MAX(a, b) ((a) > (b) ? a : b)
You can use it like this:
int hello = 12, there = 47;
int what = MAX(hello, there);
The second line will expand to:
int what = ((12) > (47) ? 12 : 47);
In other words, what will be 47. Note that this macro evaluates its arguments more than once, which can be harmful if there are side-effects.
As of C99, you can also do variadic preprocessor macros.
The code you're showing will expand to:
Str Str1;
Str(Dcn); /* This is the macro-expansion. */
I have tried to work with the container_of macro in linux kernel.
what I get by google is as follow
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) \
({ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define CONT(prt, type, mem) container_of((prt), type, mem)
struct test {
int a;
};
struct m {
int b;
struct test t;
int c;
};
int main(int argc, char *argv[])
{
/* existing structure */
struct m *ma;
ma = malloc(sizeof(struct m));
ma->t.a = 5;
ma->b = 3;
/* pointer to existing entry */
struct test *te = &ma->t;
struct m *m = CONT(te, struct m, t);
printf("m->b = %d\n", m->b);
return EXIT_SUCCESS;
}
o/p
m->b = 3
but I am having the doubt in the assignment of *m .I have tried following
#include <stdio.h>
int main()
{
int x = (int k = 9;k-2;);
printf("x= %d k = %d",x,k);
}
o/p
one.c:5: error: expected ‘)’ before ‘k’
one.c:5: error: expected expression before ‘;’ token
one.c:6: error: ‘k’ undeclared (first use in this function)
one.c:6: error: (Each undeclared identifier is reported only once
one.c:6: error: for each function it appears in.)
If this assignment is wrong here then how it is working in container of macro.what is the difference in above two.(I know one is macro and other is normal declaration but after macro expansion both will look same)
Note:Excuse me as this may be a simple but I am not able to figure it out.
kinldy give some solution to my dobut.
This is using special gcc features, namely block expressions ({ }). These allow to to have a object definition inside an expression. The last statement in this construct determines the value of the block expression.
So you missed the additional { } inside the expression for your test case.
Also:
there is no assignment in that macro, but only initialization of the local variable
the typeof operator in there also is a gcc extension
I am adding my answer to this question because I got some point .It may help other.
#include <stdio.h>
int main()
{
int x = ({int k = 9;k-2;});
printf("x = %d",x);
}
o/p
x = 7
As Jens said above its all true I have missed the { } but addition to that ,I am printing the value of k which is not correct as all the value created with in the ({ }) are temporary and will delete as soon as the value of expression is evaluated.
http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs