Enumeration syntax - c

Can someone please explain to me which part is what in this:
enum bb { cc } dd;
I understand that enum bb is the name of the enumeration and that { cc } is its enumerator, but I have no clue what dd is.

enum bb
{
cc
} dd;
bb - enum tag.
cc - enumerator constant. As it is first and it does not have an expicity defined value it will be zero (0);
dd - variable of type enum bb
It can be written as:
enum bb
{
cc
};
enum bb dd;

It defines dd as a variable of the type enum bb. Take a look at Enumerations
It behaves just like when you're defining normally
#include <stdio.h>
int main()
{
enum bb { cc, ee } dd = cc; // dd is now 0
dd = ee; // dd is now 1
printf("%d", dd);
}
Link.

Related

How to deal with strict enumerations in plain C?

Take a look at the following code:
typedef enum {
A, B, C
} Foo;
int foo(Foo x) {
switch(x) {
case A: return 1;
case B: return 2;
case C: return 3;
}
}
GCC 10.2 outputs
<source>:11:1: warning: control reaches end of non-void function [-Wreturn-type]
11 | }
| ^
This is because I can pass something like 42 to foo, not only A, B, or C. So the question is: how to tell GCC that only A, B, or C can be handled by the switch statement, otherwise the behavior is undefined? Compiler-specific functionality is acceptable.
Let me point some solutions that don't satisfy me. First, I could just insert default: __builtin_unreachable(); but this would penetrate case analysis: imagine that apparently I'm adding the D variant and the compiler would not tell me that D is unhandled.
Second, I could insert if (x > C) { __builtin_unreachable(); } before the switch statement, but this is too impossible because switch(x) is actually generated by a macro which doesn't know about the variants of Foo, it knows nothing but some variable x.
Third, I could insert #pragma GCC diagnostic ignored "-Wreturn-type", but again, switch(x) is generated by a macro and this is why I cannot revert the diagnostics to the previous state by #pragma GCC diagnostic pop.
Fourth, I could use an array instead of switch but the returned expressions are not constant and are provided by a user of the macro generating switch(x).
And the last one: I could write return 42; after the switch statement but again I want to disable the warning automatically inside the macro generating switch(x) because it's used extensively in my codebase.
Godbolt
If you feel like engaging in some light masochism, you could crudely implement exception-like behavior using setjmp and longjmp:
#include <stdlib.h>
#include <setjmp.h>
#include <stdio.h>
typedef enum Foo {
A, B, C
} Foo;
#define ENUM_OUT_OF_RANGE -1
jmp_buf env;
int foo( Foo x )
{
switch ( x )
{
case A: return 1;
case B: return 2;
case C: return 3;
default: longjmp( env, ENUM_OUT_OF_RANGE ); // "throw" ENUM_OUT_OF_RANGE
}
}
int main( void )
{
int ex;
if ( (ex = setjmp( env )) == 0 ) // "try" block
{
Foo arr[] = {A, B, C, 42};
for ( size_t i = 0; i < 4; i++ )
{
printf( "value of %d = %d\n", arr[i], foo( arr[i] ) );
}
}
else // "catch" block
{
if ( ex == ENUM_OUT_OF_RANGE )
{
fprintf( stderr, "foo was called with a value outside the range of Foo\n" );
}
}
return 0;
}
Builds with no warnings as follows (at least on my system):
gcc -o exceptions -std=c11 -pedantic -Wall -Werror exceptions.c
Output:
$ ./exceptions
value of 0 = 1
value of 1 = 2
value of 2 = 3
foo was called with a value outside the range of Foo

Append symbol name when using custom section attribute

Below is a fragment of code I'm using for an embedded system. I pass the -ffunction-sections and -fdata-sections options to gcc:
#define FAST_DATA __attribute__((section(".fast.data")))
int a1 = 1;
int a2 = 1;
FAST_DATA int a3 = 1;
FAST_DATA int a4 = 1;
The linker will allocate these symbols as below (map file):
.data.a1 0x20000020 0x4 ./main.o
0x20000020 a1
.data.a2 0x20000024 0x4 ./main.o
0x20000024 a2
.fast.data 0x10000010 0x8 ./main.o
0x10000010 a4
0x10000014 a3
If for example I don't use the variable a2, the linker will discard it (I pass --gc-sections to ld).
But if I use a3 and don't use a4, then a4 will not be discarded. I guess that's because it is placed in the same section as a3.
If I define a3 and a4 in separate .c files, they will be put in two different sections, with the same name .fast.data, but for each file. The garbage collector will work as expected.
Is there any way to tell gcc to append the symbol name even when using __attribute__((section("...")))?
For a4 in my case that would result in .fast.data.a4.
In the linker script I will catch all *(.fast.data*).
I have a large code base using custom sections a lot and manual modifications to each declaration would not be desirable.
If no one else has a better idea, here is a kludge for you:
#define DECLARE_FAST_DATA(type, name) \
__attribute__((section(".fast.data." #name))) type name
usage:
int a1 = 1;
int a2 = 1;
DECLARE_FAST_DATA(int, a3) = 1;
DECLARE_FAST_DATA(int, a4);
This uses the standard C features of "stringification" and "string literal concatenation" to synthesize the section attribute you want.
What about extending your macro?
#define FAST_DATA(_a,_b,_c) \
__attribute__((section(".fast.data." #_b))) _a _b = _c

C structure dereference chain efficiency

This one is about dereferencing stucture variables in a chain. Please consider this code:
struct ChannelInfo
{
int iData1;
int iData2;
int iData3;
int iData4;
}
struct AppInfo
{
struct ChannelInfo gChanInfo[100];
} gAppInfo;
void main()
{
gAppInfo.gChannelInfo[50].iData1 = 1;
gAppInfo.gChannelInfo[50].iData2 = 2;
gAppInfo.gChannelInfo[50].iData3 = 3;
gAppInfo.gChannelInfo[50].iData4 = 4;
foo1();
foo2();
}
void foo1()
{
printf("Data1 = %d, Data2 = %d, Data3 = %d, Data4 = %d", gAppInfo.gChannelInfo[50].iData1, gAppInfo.gChannelInfo[50].iData2, gAppInfo.gChannelInfo[50].iData3, gAppInfo.gChannelInfo[50].iData4);
}
void foo2()
{
struct ChannelInfo* pCurrrentChan = &gAppInfo.gChanInfo[50];
printf("Data1 = %d, Data2 = %d, Data3 = %d, Data4 = %d", pCurrrentChan->iData1, pCurrrentChan->iData2, pCurrrentChan->iData3, pCurrrentChan->iData4);
}
Is foo2() any faster than foo1()? What happens if the array index was not a constant, being asked for by the user? I would be grateful if someone could profile this code.
this assembly version of your code could help you understand why your code is slower. But of course it could vary depending on the target architecture and you optimization flags ( Commpiling with O2 or O3 flags produce the same code for foo1 and foo2 )
In foo2 the address of ChannelInfo is stored in a register and address are calculated relative to the value stored in the register. Or in the worst case in the stack (local variable ) where in that case it could be as slow as foo1.
In foo1 the variable address for printf are calculated relative to the variable gAppInfo stored in memory heap (or in cache ).
As per #Ludin's request I added these numbers for reference :
Execution of an instruction : 1 ns
fetch from main memory : ~100 ns
assembly version with -O2 flags ( -Os and -O3 flags produce the same code )
Pondering things like this isn't meaningful and it is pre-mature optimization, because the code will get optimized so that both those functions are equivalent.
If you for some reason would not optimize the code, foo2() will be slightly slower because it yields a few more instructions.
Please not that the call to printf is approximately 100 times slower than the rest of the code in that function, so if you are truly concerned about performance you should rather focus on avoiding stdio.h instead of doing these kinds of mini-optimizations.
At the bottom of the answer I have included some benchmarking code for Windows. Because the printf call is so slow compared to the rest of the code, and we aren't really interested in benchmarking printf itself, I removed the printf calls and replaced them with volatile variables. Meaning that the compiler is required to perform the reads no matter level of optimization.
gcc test.c -otest.exe -std=c11 -pedantic-errors -Wall -Wextra -O0
Output:
foo1 5.669101us
foo2 7.178366us
gcc test.c -otest.exe -std=c11 -pedantic-errors -Wall -Wextra -O2
Output:
foo1 2.509606us
foo2 2.506889us
As we can see, the difference in execution time of the non-optimized code corresponds roughly to the number of assembler instructions produced (see the answer by #dvhh).
Unscientifically:
10 / (10 + 16) instructions = 0.384
5.67 / (5.67 + 7.18) microseconds = 0.441
Benchmarking code:
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
struct ChannelInfo
{
int iData1;
int iData2;
int iData3;
int iData4;
};
struct AppInfo
{
struct ChannelInfo gChannelInfo[100];
} gAppInfo;
void foo1 (void);
void foo2 (void);
static double get_time_diff_us (const LARGE_INTEGER* freq,
const LARGE_INTEGER* before,
const LARGE_INTEGER* after)
{
return ((after->QuadPart - before->QuadPart)*1000.0) / (double)freq->QuadPart;
}
int main (void)
{
/*** Initialize benchmarking functions ***/
LARGE_INTEGER freq;
if(QueryPerformanceFrequency(&freq)==FALSE)
{
printf("QueryPerformanceFrequency not supported");
return 0;
}
LARGE_INTEGER time_before;
LARGE_INTEGER time_after;
gAppInfo.gChannelInfo[50].iData1 = 1;
gAppInfo.gChannelInfo[50].iData2 = 2;
gAppInfo.gChannelInfo[50].iData3 = 3;
gAppInfo.gChannelInfo[50].iData4 = 4;
const size_t ITERATIONS = 1000000;
QueryPerformanceCounter(&time_before);
for(size_t i=0; i<ITERATIONS; i++)
{
foo1();
}
QueryPerformanceCounter(&time_after);
printf("foo1 %fus\n", get_time_diff_us(&freq, &time_before, &time_after));
QueryPerformanceCounter(&time_before);
for(size_t i=0; i<ITERATIONS; i++)
{
foo2();
}
QueryPerformanceCounter(&time_after);
printf("foo2 %fus\n", get_time_diff_us(&freq, &time_before, &time_after));
}
void foo1 (void)
{
volatile int d1, d2, d3, d4;
d1 = gAppInfo.gChannelInfo[50].iData1;
d2 = gAppInfo.gChannelInfo[50].iData2;
d3 = gAppInfo.gChannelInfo[50].iData3;
d4 = gAppInfo.gChannelInfo[50].iData4;
}
void foo2 (void)
{
struct ChannelInfo* pCurrrentChan = &gAppInfo.gChannelInfo[50];
volatile int d1, d2, d3, d4;
d1 = pCurrrentChan->iData1;
d2 = pCurrrentChan->iData2;
d3 = pCurrrentChan->iData3;
d4 = pCurrrentChan->iData4;
}
yes, foo2() is definitely faster than foo1() because foo2 refers a pointer to that memory block and everytime you access it just points there and fetches value from the mmory.

Obtain a pointer to a C char array in Swift

A have a structure like this (defined in bson.h of mongodb c driver):
typedef struct
{
uint32_t domain;
uint32_t code;
char message[504];
} bson_error_t;
In Swift I have a pointer to this structure like this:
err: UnsafePointer<bson_error_t> = ...
Now whatever I do I cannot convert message[504] (which Swift sees as a tuple of (Int8, Int8, Int8, ...504 times)) to char* to use it in String.fromCString().
Is it even possible to do that in Swift? As a temporary solution I created a helper C function in a separate .c file which takes err *bson_error_t and returns char*, but this is weird if
Swift cannot do it by itself.
It's not pretty, not intuitive, but it's doable. Purely in Swift, no C glue code needed. A minimal demo:
b.h
typedef struct {
int n;
char s[8];
} Bridged;
Bridged *make_b(void);
b.c
#include <stdlib.h>
#include <string.h>
#include "b.h"
Bridged *make_b(void)
{
Bridged *p = calloc(sizeof(*p), 1);
memcpy(p->s, "foobarz", 8);
return p;
}
b.swift:
// half compile-time, half run-time black magic
func toCharArray<T>(t: T) -> [CChar] {
var a: [CChar] = []
let mirror = reflect(t)
for i in 0 ..< mirror.count {
a.append(mirror[i].1.value as CChar)
}
return a
}
let b = make_b().memory.s // bridged tuple of 8 chars
let a = toCharArray(b) // Swift array of (8) CChars
let s = String.fromCString(a) // proper Swift string
println(s)
Compile:
$ xcrun swiftc -O -c b.swift -import-objc-header b.h
$ clang -O2 -c b.c -o b.c.o
$ xcrun swiftc b.o b.c.o -o b
Run:
$ ./b
Optional("foobarz")
Here my suggestion (similar to rintaro's approach, perhaps slightly simpler):
var err: UnsafeMutablePointer<bson_error_t> = ...
var msg = err.memory.message
let msgString = withUnsafePointer(&msg) { String.fromCString(UnsafePointer($0)) }
println(msgString)
Quick hack to retrieve message String from bson_error_t:
extension bson_error_t {
mutating func messageString() -> String? {
return String.fromCString(
{ (p:UnsafePointer<Void>) in UnsafePointer<CChar>(p) }(&self.message.0)
)
}
}
// Usage:
var err: UnsafeMutablePointer<bson_error_t> = ...
...
let errMessage = err.memory.messageString()

About Linux C - UUID

#include <stdio.h>
#include <stdlib.h>
#include <uuid/uuid.h>
int main(void) {
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
uuid_t uuid;
int uuid_generate_time_safe(uuid);
printf("%x",uuid);
return EXIT_SUCCESS;
}
I just wonder why uuid is not 16 bytes long?
I use DEBUG to view the memory, It is indeed not 16 bytes.
And I use libpcap to develop my program, The uuid is not unique.
I just tried your program on my system, and uuid is 16 bytes long. But your program doesn't display its size.
The line:
int uuid_generate_time_safe(uuid);
isn't a call to the uuid_generate_time_safe function, it's a declaration of that function with uuid as the (ignored) name of the single parameter. (And that kind of function declaration isn't even valid as of the 1999 standard, which dropped the old "implicit int" rule.)
Your printf call:
printf("%x",uuid);
has undefined behavior; "%x" requires an argument of type unsigned int.
If you look in /usr/include/uuid/uuid.h, you'll see that the definition of uuid_t is:
typedef unsigned char uuid_t[16];
The correct declaration of uuid_generate_time_safe (see man uuid_generate_time_safe) is:
int uuid_generate_time_safe(uuid_t out);
You don't need that declaration in your own code; it's provided by the #include <uuid/uuid.h>.
Because uuid_t is an array type, the parameter is really of type unsigned char*, which is why the function is seemingly able to modify its argument.
Here's a more correct program that illustrates the use of the function:
#include <stdio.h>
#include <uuid/uuid.h>
int main(void) {
uuid_t uuid;
int result = uuid_generate_time_safe(uuid);
printf("sizeof uuid = %d\n", (int)sizeof uuid);
// or: printf("sizeof uuid = %zu\n", sizeof uuid);
if (result == 0) {
puts("uuid generated safely");
}
else {
puts("uuid not generated safely");
}
for (size_t i = 0; i < sizeof uuid; i ++) {
printf("%02x ", uuid[i]);
}
putchar('\n');
return 0;
}
On my system, I got the following output:
sizeof uuid = 16
uuid not generated safely
26 9b fc b8 89 35 11 e1 96 30 00 13 20 db 0a c4
See the man page for information about why the "uuid not generated safely" message might appear.
Note that I had to install the uuid-dev package to be able to build and run this program.

Resources