Initializing a const variable with ntohl() - c

I'm trying to initialize a global-scoped const variable with a value that is byte-swapped appropriately.
#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>
const uint32_t a = ntohl(0x11223344);
int main(int argc, char const *argv[])
{
printf("%08x\n", a);
return 0;
}
Using gcc this fails with "error: initializer element is not constant". Yeah, okay, so the gcc header has ntohl() defined as a function or as "do {...} while (0)" or something similar that can't be evaluated at compile time. Bummer.
Is there anything I can do which will achieve the same end? I need to initialize the value for the appropriate endedness, and I want it to be a globally-scoped const. Is there any way to convince gcc to do this, short of rolling my own ntohl-like macro?
(BTW, I note that clang has ntohl() defined such that it can be evaluated at compile time. The above code sample works perfectly with clang. Unfortunately I don't get my pick of compilers.)

Section 6.7.8/4 of the standard reads
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
A call to ntohl is neither a constant expression nor a string literal. You can’t get there from here.
But global variables are bad anyway, and I suspect this may be a premature optimization. The easy fix is to use the expression directly in your code, which will have no effect at all on big-endian platforms, e.g.,
void foo(void)
{
const unit32_t a = ntohl(0x11223344);
/* ... */
}
Even better, use a preprocessor macro, as in
#define POTRZEBIE ntohl(0x11223344)
void bar(void)
{
const unit32_t a = POTRZEBIE;
/* ... */
}
On variables with automatic storage, the const qualifier means single assignment, so there is no problem with the above usage.

Initialize it in main() or use something like (assuming Linux):
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
const uint32_t a = 0x44332211;
#else
const uint32_t a = 0x11223344;
#endif
or perhaps
#include <endian.h>
#define A_ADDR 0x11223344
#if __BYTE_ORDER == __LITTLE_ENDIAN
const uint32_t a = __bswap_constant_32(A_ADDR);
#else
const uint32_t a = A_ADDR;
#endif

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.

Compare defined expressions as text

Say I have a set of defines arranged this way:
#define Var0 ((uint32_t)0x00001)
#define Var1 ((uint32_t)0x00002)
#define Var2 ((uint32_t)0x00004)
and later in the code I have this:
#define CurrVar Var1
When I attempt to compare:
#if (CurrVar != Var1)
#error "CurrVar" has to be "Var1" for this code to work
#endif
I get:
error: token is not a valid binary operator in a preprocessor subexpression
I cannot change values of VarX since those are part of a library, but I need to make sure that a proper value is used in the code at compile time.
Is there a way to compare those expressions?
Even if it will be compared as text, like this:
"((uint32_t)0x00002)" <> "((uint32_t)0x00002)"
or
"Var1" <> "Var1"
etc
Use _Static_assert, which is in standard C from 2011 on:
_Static_assert(CurrVar == Var1, "CurrVar is not equal to Var1.");
If you must use a pre-2011 implementation of C, a common kludge is to declare an array type with an expression that is negative if an assertion fails, causing the compiler to complain about the array size:
typedef char CurrVarIsNotEqualToVar1[CurrVar == Var1 ? 1 : -1];
You can't use anything C related in such operations. Preprocessor does not understand casts and it does not compare strings.
https://godbolt.org/z/X2xuPa
#include <stdint.h>
#define V1 1
#define V2 2
#define V3 3
#define CV V1
#if CV==V1
void foo(void)
{
printf("V1\n");
}
#else
void foo(void)
{
printf("not V1\n");
}
#endif
int main(void)
{
foo();
}

C variable type assert

uint32_t fail_count = 0;
...
if(is_failed)
if(fail_count < UINT32_MAX - 1 )
++fail_count;
It works fine, but this code is fragile. Tomorrow, I may change the type of fail_count from uint32_t to int32_t and I forget to update UINT32_MAX.
Is there any way to assert fail_count is a uint32_t at the function where I have written my ifs?
P.S. 1- I know it is easy in C++ but I'm looking for a C way.
P.S. 2- I prefer to use two asserts than relying on the compiler warnings. Checking the number size via sizeof should work but is there any way to distinguish if type is unsigned?
As of C11, you can use a generic selection macro to produce a result based on the type of an expression. You can use the result in a static assertion:
#define IS_UINT32(N) _Generic((N), \
uint32_t: 1, \
default: 0 \
)
int main(void) {
uint32_t fail_count = 0;
_Static_assert(IS_UINT32(fail_count), "wrong type for fail_count");
}
You could of course use the result in a regular assert(), but _Static_assert will fail at compile time.
A better approach could be dispatching the comparison based on type, again using generic selection:
#include <limits.h>
#include <stdint.h>
#define UNDER_LIMIT(N) ((N) < _Generic((N), \
int32_t: INT32_MAX, \
uint32_t: UINT32_MAX \
) -1)
int main(void) {
int32_t fail_count = 0;
if (UNDER_LIMIT(fail_count)) {
++fail_count;
}
}
As you mentioned GCC, you can use a compiler extension to accomplish this in case you are not using C11:
First write a macro that emulates the C++ is_same. And then call it with the types you want to compare.
A minimal example for your particular case:
#include<assert.h>
#define is_same(a, b) \
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
int main()
{
int fail_count = 0;
is_same(fail_count, unsigned int);
}
The compiler asserts:
<source>: In function 'main':
<source>:4:3: error: static assertion failed: "fail_count is not unsigned int"
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
^~~~~~~~~~~~~
<source>:9:5: note: in expansion of macro 'is_same'
is_same(fail_count, unsigned int);
^~~~~~~
See Demo
What about a low-tech solution that works even with K&R C and any compiler past and present?
Place the right comment in the right place:
/*
* If this type is changed, don't forget to change the macro in
* if (fail_count < UINT32_MAX - 1) below (or file foobar.c)
*/
uint32_t fail_count = 0;
With a proper encapsulation this should refer to exactly one place in the code.
Don't tell me you increment the fail count in many places. And if you do, what
about a
#define FAIL_COUNT_MAX UINT32_MAX
right next to the declaration? That's more proper and clean code anyway.
No need for all the assertion magic and rocket sciencery :-)

typeof uses in C, besides macros

It's well known the use of typeof in Macros to make them type independent, such as container_of() and many other macros from the Linux kernel. It is unarguable that the typeof keyword unleashes a lot of power when used in these macros.
This question is about further use of the typeof keyword. What other contexts could the keyword bring lots of gain in C code, besides Macros?
One use of typeof is to const-cast a 2-dimensional array. In gcc, the construct:
extern void foo(const int a[2][2]); // or equivalently a[][2]
int a[2][2];
foo(a);
will generate:
"warning: passing argument 1 of 'foo' from incompatible pointer type".
(See http://c-faq.com/ansi/constmismatch.html for the reason why.) One way to fix this is to use a sledge-hammer-like cast, such as:
foo((void *)a);
Such a cast will happily take whatever you, perhaps mistakenly, give it.
But we can be much more delicate. By using the casting-macro CONST_CAST_2D given in the following code sample, the warning is eliminated. And more importantly, if you try to apply it to anything other than a 2-D array, you will get a compiler error/warning. CONST_CAST_PP works similarly, for a pointer-to-a-pointer.
#define CONST_CAST_2D(x) ((const typeof((x)[0][0])(*)[countof((x)[0])])(x))
#define CONST_CAST_PP(x) ((const typeof(**(x))**)(x))
#define countof(x) (sizeof(x) / sizeof 0[x]) // semi-standard define
static void foo(const int a[][2]) {} // takes const
static void bar(const int **b) {} // takes const
int main(void) {
int a[2][2]; // non-const
int **b; // non-const
foo(CONST_CAST_2D(a)); // ok
bar(CONST_CAST_PP(b)); // ok
return 0;
}
CONST_CAST_PP provides a clean and robust solution to a commonly-asked problem, e.g.:
Double pointer const-correctness warnings in C
c compiler warning when passing a char *arr[] to a function as const char **arr
What type is the reference to an array variable?
const cast and pointers to pointers
Why it's not safe to cast `char **` to `const char **`?
Why does implicit conversion from non-const to const not happen here?
Intel C++ Compiler warning 167 when non-const argument is passed as const parameter
And CONST_CAST_2D resolves:
How to eliminate warning for passing multidimensional array as const multidimensional array?
C function const multidimensional-array argument strange warning
A second usage of typeof is to generate pointers to constants, or pointers to function return values, as shown in the following example:
#include <stdio.h>
#include <time.h>
#include <sys/socket.h>
#define AMPERSAND(x) (&(typeof(x)){x})
int main(void) {
printf("%s\n", ctime(AMPERSAND(time(0)))); // pointer to time_t
setsockopt(0, SOL_SOCKET, SO_REUSEADDR, AMPERSAND(1), sizeof 1);
return 0;
}
This allows for straight-forward function composition, rather than having to save temporaries in named variables. (Unfortunately this doesn't extend to g++.)
Some people (myself included) dislike the syntax of the C++ const_cast<> operator, because;
It seems misnamed, because it removes const.
It seems to violate DRY, because it requires a redundant type arg.
But I am wrong: it is not misnamed, since it can also add const and/or volatile "cv" qualifiers, and it only partially violates DRY, since the compiler will catch any errors. So I dislike it slightly less and use it: it is safer than the C-style cast.
Using gcc's typeof, you can have almost the same type safety in C.
The following C code sample gives a CONST_CAST(T, x) macro, and illustrates its use:
#define REMOVE_QUALIFIER(cv, T, x) /* this macro evaluates its args only once */ \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), cv T), ((T)(x)), \
(void)0)
#define ADD_QUALIFIER(cv, T, x) /* this macro evaluates its args only once */ \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), T), ((cv T)(x)), \
(void)0)
#ifdef __GNUC__
#define CONST_CAST(T, x) REMOVE_QUALIFIER(const, T, x) // "misnamed"
#else
#define CONST_CAST(T, x) ((T)(x)) // fallback to standard C cast
#endif
void foo(void);
void foo(void) {
const int *a = 0;
const float *x = 0;
int *b = a; // warning
int *c = (int *)a; // no warning, unsafe standard cast
int *d = (int *)x; // no warning, and likely wrong
int *e = CONST_CAST(int *, a); // ok
int *f = CONST_CAST(int *, x); // error
unsigned *g = CONST_CAST(unsigned *, a); // error
const int **h = &b; // warning
const int **i = ADD_QUALIFIER(const, int **, &b); // ok
const int **j = ADD_QUALIFIER(const, int **, &x); // error
}
This technique can also be used to change the signedness of a type, reminiscent of C++'s std::make_signed and std::make_unsigned, or Boost traits. For example:
#define MAKE_UNSIGNED(T, x) ADD_QUALIFIER(unsigned, T, x) // T usually char*
This use of gcc's typeof is yet another reinterpret cast, using union-punning.
It can be applied to scalars and structures, as well as to pointers. It gives only an R-value.
#ifdef __GNUC__
#define PUN_CAST(T, x) (((union {typeof(x) src; T dst;})(x)).dst)
#else
#define PUN_CAST(T, x) (*(T*)&(x)) //<-- classic pun: breaks strict aliasing rules
#endif
Caveat: you can use this to cast a pointer into an array of 4 or 8 bytes, or vice versa. But you can't use it to cast a pointer into another pointer, in an attempt to avoid the strict aliasing rules.

Typechecking macro arguments in C

Is it possible to typecheck arguments to a #define macro? For example:
typedef enum
{
REG16_A,
REG16_B,
REG16_C
}REG16;
#define read_16(reg16) read_register_16u(reg16); \
assert(typeof(reg16)==typeof(REG16));
The above code doesn't seem to work. What am I doing wrong?
BTW, I am using gcc, and I can guarantee that I will always be using gcc in this project. The code does not need to be portable.
gcc supports typeof
e.g. a typesafe min macro taken from the linux kernel
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
but it doesn't allow you to compare two types. Note though the pointer comparison which Will generate a warning - you can do a typecheck like this (also from the linux kernel)
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
Presumably you could do something similar - i.e. compare pointers to the arguments.
The typechecking in C is a bit loose for integer-related types; but you can trick the compiler by using the fact that most pointer types are incompatible.
So
#define CHECK_TYPE(var,type) { __typeof(var) *__tmp; __tmp = (type *)NULL; }
This will give a warning, "assignment from incompatible pointer type" if the types aren't the same. For example
typedef enum { A1,B1,C1 } my_enum_t;
int main (int argc, char *argv) {
my_enum_t x;
int y;
CHECK_TYPE(x,my_enum_t); // passes silently
CHECK_TYPE(y,my_enum_t); // assignment from incompatible pointer type
}
I'm sure that there's some way to get a compiler error for this.
This is an old question, But I believe I have a general answer that according to Compiler Explorer apears to work on MSVC, gcc and clang.
#define CHECK_TYPE(type,var) { typedef void (*type_t)(type); type_t tmp = (type_t)0; if(0) tmp(var);}
In each case the compiler generates a useful error message if the type is incompatible. This is because it imposes the same type checking rules used for function parameters.
It can even be used multiple times within the same scope without issue. This part surprises me somewhat. (I thought I would have to utilize "__LINE__" to get this behavior)
Below is the complete test I ran, commented out lines all generate errors.
#include <stdio.h>
#define CHECK_TYPE(type,var) { typedef void (*type_t)(type); type_t tmp = (type_t)0; if(0) tmp(var);}
typedef struct test_struct
{
char data;
} test_t;
typedef struct test2_struct
{
char data;
} test2_t;
typedef enum states
{
STATE0,
STATE1
} states_t;
int main(int argc, char ** argv)
{
test_t * var = NULL;
int i;
states_t s;
float f;
CHECK_TYPE(void *, var); //will pass for any pointer type
CHECK_TYPE(test_t *, var);
//CHECK_TYPE(int, var);
//CHECK_TYPE(int *, var);
//CHECK_TYPE(test2_t, var);
//CHECK_TYPE(test2_t *, var);
//CHECK_TYPE(states_t, var);
CHECK_TYPE(int, i);
//CHECK_TYPE(void *, i);
CHECK_TYPE(int, s); //int can be implicitly used instead of enum
//CHECK_TYPE(void *, s);
CHECK_TYPE(float, s); //MSVC warning only, gcc and clang allow promotion
//CHECK_TYPE(float *, s);
CHECK_TYPE(float, f);
//CHECK_TYPE(states_t, f);
printf("hello world\r\n");
}
In each case the compiler with -O1 and above did remove all traces of the macro in the resulting code.
With -O0 MSVC left the call to the function at zero in place, but it was rapped in an unconditional jump which means this shouldn't be a concern. gcc and clang with -O0 both remove everything except for the stack initialization of the tmp variable to zero.
No, macros can't provide you any typechecking. But, after all, why macro? You can write a static inline function which (probably) will be inlined by the compiler - and here you will have type checking.
static inline void read_16(REG16 reg16) {
read_register_16u(reg16);
}
Building upon Zachary Vander Klippe's answer, we might even go a step further (in a portable way, even though that wasn't a requirement) and additionally make sure that the size of the passed-in type matches the size of the passed-in variable using the "negative array length" trick that was commonly used for implementing static assertions in C (prior to C11, of course, which does provide the new _Static_assert keyword).
As an added benefit, let's throw in some const compatibility.
#define CHECK_TYPE(type,var) \
do {\
typedef void (*type_t) (const type);\
type_t tmp = (type_t)(NULL);\
typedef char sizes[((sizeof (type) == sizeof (var)) * 2) - 1];\
if (0) {\
const sizes tmp2;\
(void) tmp2;\
tmp (var);\
}\
} while (0)
Referencing the new typedef as a variable named tmp2 (and, additionally, referencing this variable, too) is just a method to make sure that we don't generate more warnings than necessary, c.f., -Wunused-local-typedefs and the like. We could have used __attribute__ ((unused)) instead, but that is non-portable.
This will work around the integer promotion "issue" in the original example.
Example in the same spirit, failing statements are commented out:
#include <stdio.h>
#include <stdlib.h>
#define CHECK_TYPE(type,var) \
do {\
typedef void (*type_t) (const type);\
type_t tmp = (type_t)(NULL);\
typedef char sizes[((sizeof (type) == sizeof (var)) * 2) - 1];\
if (0) {\
const sizes tmp2;\
(void) tmp2;\
tmp (var);\
}\
} while (0)
int main (int argc, char **argv) {
long long int ll;
char c;
//CHECK_TYPE(char, ll);
//CHECK_TYPE(long long int, c);
printf("hello world\n");
return EXIT_SUCCESS);
}
Naturally, even that approach isn't able to catch all issues. For instance, checking signedness is difficult and often relies on tricks assuming that a specific complement variant (e.g., two's complement) is being used, so cannot be done generically. Even less so if the type can be a structure.
To continue the idea of ulidtko, take an inline function and have it return something:
inline
bool isREG16(REG16 x) {
return true;
}
With such as thing you can do compile time assertions:
typedef char testit[sizeof(isREG16(yourVariable))];
No. Macros in C are inherently type-unsafe and trying to check for types in C is fraught with problems.
First, macros are expanded by textual substitution in a phase of compilation where no type information is available. For that reason, it is utterly impossible for the compiler to check the type of the arguments when it does macro expansion.
Secondly, when you try to perform the check in the expanded code, like the assert in the question, your check is deferred to runtime and will also trigger on seemingly harmless constructs like
a = read_16(REG16_A);
because the enumerators (REG16_A, REG16_B and REG16_C) are of type int and not of type REG16.
If you want type safety, your best bet is to use a function. If your compiler supports it, you can declare the function inline, so the compiler knows you want to avoid the function-call overhead wherever possible.

Resources