How to determine if a declared extern variable is defined or initialized in some C file - arrays

I have some table of structs that get compiled differently depending on what driver I am using.
I want to be able to check if a certain driver has been compiled (or by relation, if its table is defined).
I've look all over but I can't seem to find a way to determine if a declared extern variable has been defined or
if there's some way to check if a c source file has been compiled (and linked) within a given application. I had looked at using some macro magic like the container_of macro however I've so far come up short.
for example say I have the following:
checkFile.c
#include "neutral.h"
#include "fileA.h"
#include "fileB.h"
bool setTable(int type, someStruct_t *table) {
/*
This doesn't work
fails to compile with:
undefined reference to fileA_Table
ironically this is what I'm trying to check
*/
switch (type) {
case FILEA:
if (fileA_Table) {
someTable = &fileA_Table;
return true;
}
else {
someTable = NULL;
return false;
}
break;
case FILEB:
if (fileB_Table) {
someTable = &fileB_Table;
return true;
}
else {
someTable = NULL;
return false;
}
break;
default:
someTable = NULL;
return false;
}
}
neutral.h
typedef struct {
int memberA;
bool memberB;
} someStruct_t;
extern someStruct_t fileA_table[];
extern someStruct_t fileB_table[];
fileA.c
#include "neutral.h"
someStruct_t fileA_table[] = {
{
.memberA = 0;
.memberB = false;
},
{
.memberA = 5;
.memberB = false;
}
}
fileB.c
#include "neutral.h"
someStruct_t fileB_table[] = {
{
.memberA = 14;
.memberB = true;
},
{
.memberA = 5;
.memberB = true;
}
}
I'm not even sure that this is something that I can do in C and really the fundamental problem I'm trying to solve is initializing some type of interface that relies on fileA or fileB and ensuring which arrays are available to use from fileA and/or fileB. Note this
Ideally I'd actually like if I could just use file_table but I don't think that's possible if both fileA and fileB are compiled.
Note this should work regardless of if fileA or fileB or both files are compiled.
Any help is much appreciated.

Your code can safely assume that the variable exists.
If it doesn't, you'll get an error from the compiler during the linking stage when you attempt to link your object files into an executable.
If you want some kind of conditional compilation, you'll need to set a macro based on what's available and then check for that macro in various parts of your code.
For example:
#include "neutral.h"
#ifdef USE_FILE_A
#include "fileA.h"
#elif defined USE_FILE_B
#include "fileB.h"
#endif
bool setTable(someStruct_t **table)
{
#ifdef USE_FILE_A
*table= &fileA_Table;
return true;
#elif defined USE_FILE_B
*table= &fileB_Table;
return true;
#else
*table = NULL;
return false;
}
With the updated code:
#include "neutral.h"
#ifdef HAS_FILE_A
#include "fileA.h"
#endif
#ifdef HAS_FILE_B
#include "fileB.h"
#endif
bool setTable(int type, someStruct_t *table)
{
switch (type) {
case FILEA:
#ifdef HAS_FILE_A
someTable = &fileA_Table;
return true;
#else
someTable = NULL;
return false;
#endif
break;
case FILEB:
#ifdef HAS_FILE_B
someTable = &fileB_Table;
return true;
#else
someTable = NULL;
return false;
#endif
break;
default:
someTable = NULL;
return false;
}
}

Based on Bill Lynch's suggestion I looked into strong and weak symbols here and here and found an appealing solution. Roughly this is what I came up with.
checkFile.c
#include "neutral.h"
#include "fileA.h"
#include "fileB.h"
bool setTable(int type, someStruct_t *table) {
/*
* This will compile and if fileA_table has not been
* defined in fileA then it will evaluate to 0
*/
switch (type) {
case FILEA:
if (fileA_Table) {
someTable = &fileA_Table;
return true;
}
else {
someTable = NULL;
return false;
}
break;
case FILEB:
if (fileB_Table) {
someTable = &fileB_Table;
return true;
}
else {
someTable = NULL;
return false;
}
break;
default:
someTable = NULL;
return false;
}
}
neutral.h
typedef struct {
int memberA;
bool memberB;
} someStruct_t;
__attribute__((weak)) extern someStruct_t fileA_table[];
__attribute__((weak)) extern someStruct_t fileB_table[];
fileA.c
#include "neutral.h"
someStruct_t fileA_table[] = {
{
.memberA = 0;
.memberB = false;
},
{
.memberA = 5;
.memberB = false;
}
}
fileB.c
#include "neutral.h"
someStruct_t fileB_table[] = {
{
.memberA = 14;
.memberB = true;
},
{
.memberA = 5;
.memberB = true;
}
}
I like this since it meant I could get the results I want with minimal impact to my interface and no impact to compiler options/commands.
I would have liked to use the same symbol for fileA and fileB to make the generic interface layer and the neutral header cleaner to get something like this:
neutral.h
typedef struct {
int memberA;
bool memberB;
} someStruct_t;
__attribute__((weak)) extern someStruct_t file_table[];
checkFile.c
#include "neutral.h"
#include "fileA.h"
#include "fileB.h"
bool setTable(int type, someStruct_t *table) {
if (file_Table) {
someTable = &file_table;
return true;
}
someTable = NULL;
return false;
}
This could be done so long as we compile the interface starting at checkFile.c as two seperate binaries. Once linking with fileA.c and once with fileB.c. This does add some complexity in build options, increases code size, and I'm not sure of the impact to performance however it makes the code more maintainable and much more so should there be several potential files and several types of tables that need to be checked.

Related

function pointers and enum in C

I am looking for a fancy way to link function pointers and enums.
In my case I have a message queue that holds a event id and some data associated with the event.
some simple pseudo code:
event=(eid, data)
switch(eid) {
case eid1:
handler1(data);
break;
case edi2:
handler2(data);
break;
}
Now I like to do some optimization. If the event id has the value of the function called inside of the switch case statement I can save the switch case decode by preserving a nice readability of the code.
event=(eid, data)
eid(data)
Now if I am putting it into an example like:
static void abc(void * p) {
}
static void abc2(void * p) {
}
enum eventId {
eid1 = abc,
eid2 = abc2
} xyz;
My compiler tells:
error: enumerator value for 'eid1' is not an integer constant eid1 = abc
What is absolutely right.
Any ideas how to solve that problem?
Use an array of function pointers, and use the enum as the index.
typedef void (*handler_func)(void *);
handler_func event_handlers[] = { abc, abc2 };
enum eventId {
eid1 = 0,
eid2 = 1,
eid_max
}
if (eid < eid_max) event_handlers[eid](data);
enums cannot be linked with other data in C, but the preprocessor can generate code for you in the form of X-Macros.
#include <stdio.h>
typedef void (*handler_func)(void *);
static void handler1(void *const param) {
printf("Event 1: %p.\n", param);
}
static void handler2(void *const param) {
printf("Event 2: %p.\n", param);
}
#define EVENT(X) \
X(EID1, &handler1), \
X(EID2, &handler2)
#define PARAMA(A, B) A
#define PARAMB(A, B) B
#define STRINGISEA(A, B) #A
enum Event { EVENT(PARAMA) };
static const handler_func event_handlers[] = { EVENT(PARAMB) };
static const char *const event_strings[] = { EVENT(STRINGISEA) };
/* Everything will be the same size, pick one. */
static const size_t event_size = sizeof event_strings / sizeof *event_strings;
int main(void) {
size_t i;
void *const param = (void *)0x100;
for(i = 0; i < event_size; i++) {
printf("Calling %s.\n", event_strings[i]);
event_handlers[i](param);
}
return 0;
}
Gives,
Calling EID1.
Event 1: 0x100.
Calling EID2.
Event 2: 0x100.
The advantage of this implementation is it's a single source of truth; if one decided to add more events, they will only need to be added in one spot. The disadvantage is it's hard to read.
As an extension to the answer of #Barmar, you can use a technique called X macro, to keep corresponding (eid, handler) pairs in order. Note that you need only to change the definition of LIST_OF_EVENTS macro, adding or deleting pairs as needed.
void handler1(void*);
void handler2(void*);
void handler3(void*);
#define LIST_OF_EVENTS X(eid1, handler1), X(eid2, handler2), X(eid3, handler3)
#define X(id, x) id
enum evID { LIST_OF_EVENTS };
#undef X
#define X(x, handler) handler
void (*handlers[])(void*) = { LIST_OF_EVENTS };
#undef X
int get_event(void**);
void event_loop(void)
{
for (;;) {
void *data;
int eid = get_event(&data);
handlers[eid](data);
}
}
Macro defitions expand to
enum evID { eid1, eid2, eid3 };
void (*handlers[])(void*) = { handler1, handler2, handler3 };

How to include macro in struct

I am trying to find a way to dynamically access a certain macro in C.
I tried to include the macro in the struct but then I get the "initializer element is not constant" error. Basically I just want to access the correct macro based on an index but I just don't know how. Is there a straight forward way of accomplishing this? Please note the code is not complete but only an illustration of what I want to do.
#define Data_CAN_SES_Enbl() (...)
#define Data_CAN_SAS_Enbl() (...)
#define Data_CAN_PEP_Enbl() (...)
struct CAN_Rx {
const uint8 id;
const uint8 bus;
xx
};
static struct CAN_Rx CheckRx[] = {
/* SES */
{
0,0,?
},
/* SAS */
{
1,0,?
},
/* PEP */
{
2,1,?
}
};
void run(uint8 index)
{
uint8 enabled = CheckRx[index].xx;
}
Simply put: you won't.
Dont think of macros as code: they're just chunk of text replaced by the preprocessor before compiling your code.
If you need to embed code in a struct, you better look at function pointers.
--- EDIT ---
By the way, why you want to use macro in your code? Looking at it, it seems you cand do the same thing with a simple function returning a struct with a different content based on a parameter, like:
static struct CAN_Rx getCANrx(int index){
switch(index)
{
case '0':
struct CAN_rx res = /* initialize struct */;
return res;
case '1':
/* as previous */
default:
/* manage default result or errors */
}
}
Maybe you can go with function pointers?
#include <stdio.h>
int Data_CAN_SES_Enbl() { return 0; }
int Data_CAN_SAS_Enbl() { return 1; }
int Data_CAN_PEP_Enbl() { return 2; }
struct CAN_Rx {
const int id;
const int bus;
int (*xx)();
};
static struct CAN_Rx CheckRx[] = {
/* SES */
{
0,0,Data_CAN_SES_Enbl
},
/* SAS */
{
1,0,Data_CAN_SAS_Enbl
},
/* PEP */
{
2,1,Data_CAN_PEP_Enbl
}
};
int run(int index)
{
int enabled = (*CheckRx[index].xx)();
return enabled;
}
int main() {
printf("%d\n",run(0));
}
If you are curious see below macro example.
For your case , macro cant be better than function pointers.
Using macro just for fun at your case.
#include <stdio.h>
#include <stdlib.h>
#define Data_CAN_SES_Enbl(Y,Z) Y+Z
#define Data_CAN_SAS_Enbl(Y,Z) Y*Z
#define Data_CAN_PEP_Enbl(Y,Z) Y-Z
#define Str(X) #X
#define Data_CAN_Enbl(X,Y,Z) Data_CAN_##X##_Enbl(Y,Z);
#define SES 1
#define SAS 2
#define PEP 3
struct CAN_Rx {
int id;
int bus;
int Flag;
};
static struct CAN_Rx CheckRx[] = {
/* SES */
{
0,100,SES
},
/* SAS */
{
70,20,SAS
},
/* PEP */
{
100,50,PEP
}
};
void run(int index)
{
int RRR=0;
switch(CheckRx[index].Flag){
case SES:
RRR=Data_CAN_Enbl(SES,CheckRx[index].id,CheckRx[index].bus);
printf("%s :%d\n",_Str(SES),RRR);
break;
case SAS:
RRR=Data_CAN_Enbl(SAS,CheckRx[index].id,CheckRx[index].bus);
printf("%s :%d\n",_Str(SAS),RRR);
break;
case PEP:
RRR=Data_CAN_Enbl(PEP,CheckRx[index].id,CheckRx[index].bus);
printf("%s :%d\n",_Str(PEP),RRR);
break;
}
}
int main(){
run(0);
run(1);
run(2);
printf("%d\n",CheckRx[0].Flag);
return 0;
}

How to protect enum assignment

I want to prevent invalid value enum assignment. I know if i even assign value that is not in enum it will work. Example:
enum example_enum
{
ENUM_VAL0,
ENUM_VAL1,
ENUM_VAL2,
ENUM_VAL3
};
void example_function(void)
{
enum example_enum the_enum = ENUM_VAL3; // correct
the_enum = 41; // will work
the_enum = 0xBADA55; // also will work
bar(the_enum); // this function assumes that input parameter is correct
}
Is there easy, efficient way to check if assignment to enum is correct? I could test value by function
void foo(enum example_enum the_enum)
{
if (!is_enum(the_enum))
return;
// do something with valid enum
}
I could resolve this in following way:
static int e_values[] = { ENUM_VAL0, ENUM_VAL1, ENUM_VAL2, ENUM_VAL3 };
int is_enum(int input)
{
for (int i=0;i<4;i++)
if (e_values[i] == input)
return 1;
return 0;
}
For me, my solution is inefficient, how can i write this if i have more enums and more values in enums?
As long as the enum is continuous one can do something like this:
static int e_values[] = { ENUM_VAL0, ENUM_VAL1, ENUM_VAL2, ENUM_VAL3, ENUM_VAL_COUNT };
int is_enum(int input) { return 0 <= input && input < ENUM_VAL_COUNT; }
Another alternative is to not validate the enum value beforehand, but error out once the code detects an invalid value:
switch(input) {
case ENUM_VAL0: ... break;
case ENUM_VAL1: ... break;
...
default:
assert(0 && "broken enum");
break;
}
But there is no way to enforce that the enum value doesn't go out of the range at all in C. The best you can do if you want to secure the enum against fiddling is to hide the value away in a struct and then have functions to manipulate the struct. The function and struct implementation can be hidden away from the user via a forward declaration in the .h file and the implementation in the .c file:
struct example_t {
enum example_enum value;
}
void example_set_val0(example_t* v) { v->value = ENUM_VAL0; }
There is no way of warning about assigning integers that fit into the enum.
Enumerators in C are synonyms for integer types. Assuming the type chosen for enum example_enum is int, then your code is identical to:
void example_function(void)
{
int the_enum = ENUM_VAL3; // correct
the_enum = 12345; // will work
bar(the_enum); // this function assumes that input parameter is correct
}
void foo(int the_enum)
{
if (!is_enum(the_enum))
return;
// do something with valid enum
}
You could use structures, but even that can be circumvented:
struct example_enum_struct e = { 12345 };
e.value = 23456;
Basically if you want to restrict a type to specific values, you will need to perform checks.
If anyone is interested in this topic, here I have some solution which works.
typed_enums.h
#ifndef TYPED_ENUMS_H
#define TYPED_ENUMS_H
#define TYPED_ENUM(name_) \
typedef struct { int v; } name_
#define TYPED_ENUM_VALUE(name_, value_) (name_) { value_ }
#define GET_TYPED_ENUM_VALUE(en_) (en_.v)
#define TYPED_ENUM_EQ(a_, b_) (GET_TYPED_ENUM_VALUE(a_) == GET_TYPED_ENUM_VALUE(b_))
#endif
usb_class.h
#ifndef USB_CLASS_H
#define USB_CLASS_H
#include "typed_enums.h"
TYPED_ENUM(UsbClass);
#define USB_CLASS_BILLBOARD TYPED_ENUM_VALUE(UsbClass, 0x11)
#define USB_CLASS_TYPE_C_BRIDGE TYPED_ENUM_VALUE(UsbClass, 0x12)
#define USB_CLASS_DIAGNOSTIC_DEVICE TYPED_ENUM_VALUE(UsbClass, 0xDC)
#define USB_CLASS_WIRELESS_CONTROLLER TYPED_ENUM_VALUE(UsbClass, 0xE0)
#endif
usb_class_example.c
#include "typed_enums.h"
#include "usb_class.h"
#include <stdio.h>
int main(int argc, char ** argv)
{
UsbClass usbClass = USB_CLASS_WIRELESS_CONTROLLER;
usbClass = 12345; // tadam!!!! throws error
usbClass = USB_CLASS_VIDEO;
if (TYPED_ENUM_EQ(usbClass, USB_CLASS_VIDEO)) {
printf("usbClass = USB_CLASS_VIDEO\n");
}
printf("usb class value: %02X\n", GET_TYPED_ENUM_VALUE(usbClass));
return 0;
}
Pros:
enum value assignment works like struct assignment
enum for pointers also works
enum value can't be changed
Cons:
can't be used in switch
can't be directly compared
can't directly return enum number value
Note: sorry for abusing preprocessor here

How to check if stdout has been redirected to NUL on Windows (a.k.a. /dev/null on Linux)?

How can I check if my program's stdout has been redirected to NUL?
That way I can avoid outputting data since it's pointless.
I mainly need this for Windows, but if you have a Linux solution, it might be helpful for others in the future, so feel free to post that as well.
There are probably other ways to do this (and it wouldn't be a surprise if there turns out to be a proper function for it I've overlooked), but here's one way:
enum
{
Output_Console,
Output_File,
Output_NUL,
};
bool GetOutputHandleType(int* piType)
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
if (h)
{
BY_HANDLE_FILE_INFORMATION fi;
if (GetFileInformationByHandle(h, &fi))
{
*piType = Output_File;
return true;
}
if (GetLastError() == ERROR_INVALID_FUNCTION)
{
*piType = Output_NUL;
return true;
}
if (GetLastError() == ERROR_INVALID_HANDLE)
{
*piType = Output_Console;
return true;
}
}
return false;
}
I figured it out myself. It's annoying.
#include <Windows.h>
#include <io.h>
#pragma comment(lib, "ntdll.lib") // can instead use GetProcAddress (below)
extern "C" NTSTATUS __stdcall NtQueryVolumeInformationFile(
HANDLE FileHandle, struct _IO_STATUS_BLOCK *IoStatusBlock,
void *FsInformation, unsigned long Length,
enum _FSINFOCLASS FsInformationClass);
bool isdevnull(FILE *file)
{
struct FILE_FS_DEVICE_INFORMATION
{ unsigned long DeviceType, Characteristics; } fsinfo;
struct { void *info, *status; } iosb;
typedef NTSTATUS (__stdcall *PNTQIF)(
HANDLE FileHandle, struct _IO_STATUS_BLOCK *IoStatusBlock,
void *FsInformation, unsigned long Length,
enum _FSINFOCLASS FsInformationClass);
PNTQIF const ntqif =
true // True if you have ntdll.lib, false otherwise
? NtQueryVolumeInformationFile
: (PNTQIF) GetProcAddress(
GetModuleHandle(TEXT("ntdll.dll")),
"NtQueryVolumeInformationFile");
return ntqif(
(HANDLE) _get_osfhandle(_fileno(stdout)),
(struct _IO_STATUS_BLOCK *)&iosb,
&fsinfo, sizeof(fsinfo),
(enum _FSINFOCLASS)4
) == 0 && fsinfo.DeviceType == 0x00000015 /*FILE_DEVICE_NULL*/;
}
int main()
{
bool b = isdevnull(stdout);
}

"called object is not a function" error - C

int getSpeedOfMotorInPercent(int RPM)
{
int speedOfMotor = (RPM/5000.0)*100;
return speedOfMotor;
}
static char *test_GetSpeedOfMotor(int speedInPercent)
{
mu_assert("error, RPM != 70%", speedInPercent == 70);
return 0;
}
static char *run_all_tests(int RPM)
{
mu_run_test(test_GetSpeedOfMotor(RPM));
return 0;
}
I get the error "called object is not a function" on mu_run_test(test_GetSpeedOfMotor(RPM));
I tried removing the pointer of the function but then I get even more errors.
EDIT:
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++; if (message) return message; } while (0)
extern int tests_run;
this is the mu_run_test function. It is provided to me like that in the header file.
You're passing test_GetSpeedOfMotor(RPM) as test in the macro, which will result in this code:
char *message = test_GetSpeedOfMotor(RPM)();
Since you're probably using a test framework which you don't want to change, just remove the RPM parameter from the declaration of test_GetSpeedOfMotor function and use it like this:
int testRpmInPercent;
static char *test_GetSpeedOfMotor()
{
mu_assert("error, RPM != 70%", testRpmInPercent == 70);
return 0;
}
static char *run_all_tests(int RPM)
{
testRpmInPercent = RPM;
mu_run_test(test_GetSpeedOfMotor);
return 0;
}
Then you'll have to find an other way of sharing the RPM value with the test function. Like a global variable or with whatever method the test framework has to offer.
If you're willing to change the test framework, I would modify that define to this (remove () after test):
#define mu_run_test(test) do { char *message = test; tests_run++; if (message) return message; } while (0)

Resources