Automatically replacing variables with #defines - c

I have a file with about 100 #defines in it, from 1-100, and each with a unique string value.
Now I'm trying to print this value, but instead of the value, I want to print what the #define is. For example:
#define FIRST_VALUE 1
var = FIRST_VALUE;
printf("%s", var);
and I want the printf to print FIRST_VALUE, not 1.
Is there any way to do this in C? Or must I just write out 100+ case blocks inside a switch statement?

You can use stringification to achieve what you are looking for:
#define FIRST_MACRO
#define MACRO_TO_STRING(x) #x
#include <stdio.h>
main() {
printf("%s\n", MACRO_TO_STRING(FIRST_MACRO));
}
This program will output:
FIRST_MACRO

After talking to one of my TA's at school, we've decided that the best way to do this would be to write an AWK script to process the header file and automatically generate all the case statements needed.
Thanks guys!

You can't do exactly what you want, since by the time the compiler gets the pre-processor output, the "ONE" token is long gone. However, if your goal is to write the list of constants once but generate both tokens and strings, then this can be done.
First, use a macro to build the constants as enums in a header file. File enums.h:
#ifndef ENUMS_H
#define ENUMS_H
#ifndef ENUM
#define ENUM(name,val) enum { name = val };
#endif
ENUM(ONE,1)
ENUM(TWO,2)
ENUM(THREE,3)
#endif /* ENUMS_H */
Second, redefine the macro in a .c file to create a string/integer mapping and include the .h file in the right place. File enums.c:
#include
#include
typedef struct {
char *str;
int val;
} DescriptiveEnum;
static DescriptiveEnum enums[] = {
#define ENUM(name,val) { #name, val },
#include "enums.h"
};
#define NUM_ENUMS (sizeof(enums)/sizeof(enums[0]))
char *enum_to_str(int val)
{
int i;
for (i=0;i<NUM_ENUMS;i++) {
if (enums[i].val == val) return enums[i].str;
}
return "";
}
Now both the enum constants and the mapping function are available to callers. File main.c:
#include <stdio.h>
#include <stdlib.h>
#include "enums.h"
char *enum_to_str(int val);
int main(int argc, char *argv[])
{
int val;
val = ONE;
printf("%d %s\n",val,enum_to_str(val));
return EXIT_SUCCESS;
}

Related

Unable to retrieve a value inside a c header file

I have a header file where a few functions needs to be implemented in the header file and included in a main.c file to be tested. These are some library functions of String and encoding.
Once these methods are implemented in the header file I should be able to include this file in another c file and execute these methods.
#ifndef ABSTRING_H
#define ABSTRING_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define ABSBLOCK 4096
typedef struct _abstring
{
unsigned char* val;
size_t length;
size_t space;
}absval;
abstring absval;
//Initialize string
abstring* initAbs() {
printf("%s", abval.val);
printf("%zu", abval.val);
abval.length = sizeof(abval.val);
abval.space = ABSBLOCK - sizeof(abval.val);
return &abval;
}
------------------ End of the header file (abString.h ) ------------------------
main.c file
#include "abString.h"
int main()
{
abstring absinit;
absinit.val = "abString";
printf("ABSBLOCK block size : %d .\n", ABSBLOCK);
initAbs();
return 0;
}
The issue I'm having is once I define a val in the main c file I'm not able to retrieve that value inside my header file in order to initialize the length and space.

Define a variable in header file works only when extern keyword is not present? [duplicate]

This question already has answers here:
Variable declaration in a header file [duplicate]
(5 answers)
Closed 4 years ago.
I am learning at moment C and I really do not understand how header
files works and to be sure I have two Questions.
1) Let's take a look at the following program: main.c:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main( void )
{
printf( "Num = %d\n", number );
printNumber();
return 0;
}
functions.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "functions.h"
void printNumber( void )
{
printf("Number = %d\n", number );
}
functions.h:
#ifndef FUNCTIONS
#define FUNCTIONS
int number;
extern void printNumber( void );
#endif // FUNCTIONS
The way the program is in the Header file there is no extern keyword
involved so there seems to be reference to number and the program
Outputs:
Num = 0
Number = 0
The first Question is, does number get initialized (is number global
variable or similar if number is present only in the header file)
and is this a legal code/program?
Second scenario, let's take a look at the following code main.c:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main( void )
{
printf( "Num = %d\n", number );
printNumber();
return 0;
}
functions.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "functions.h"
void printNumber( void )
{
printf("Number = %d\n", number );
}
functions.h:
#ifndef FUNCTIONS
#define FUNCTIONS
extern int number;
extern void printNumber( void );
#endif // FUNCTIONS
Here the program will not compile due the
`undefined reference to number`
Which force me to declare number in main:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int number;
int main( void )
{
printf( "Num = %d\n", number );
printNumber();
return 0;
}
Which is the Right way and why?
Last thing, why does exactly not apply
to void printNumber( void ) as well. I see that it is working with
or without the extern keyword.
For the first version, in your header file, you define the variable number. That means every translation unit that includes the header file will have a definition of the variable. That's not allowed, you can only have a single definition spread over all translation units.
The solution to that problem is to declare the variable in the header file instead:
extern int number;
The use of the keyword extern marks this as a declaration instead of a definition, the compiler will know that the variable is defined somewhere else.
Then you of course need to define it somewhere. In one single source file put the definition:
int number;
I.e. exactly what you do in your last variant.
In addition to Some programmer dude's answer, I use the following construct:
// functions.h
#indef EXTERN
# define EXTERN extern
#endif
EXTERN int number;
// functions.c
#include "functions.h"
// main.c
#define EXTERN
#include "functions.h"
When main compiles, storage will be allocated for number. In all other source files, it will be declared as extern.

Multiple Definition of a function in C, Prototyping

Eclipse tells me that I have mutliple Definitions of a function.
I just can't spot the mistake.
This is my main.c
#include <stdio.h>
#include "kontaktverzeichnis.h"
int main(){
kontakt_hinzufuegen();
return 0;
}
This is the header:
#ifndef KONTAKTVERZEICHNIS_H_
#define KONTAKTVERZEICHNIS_H_
#include "kontaktfunktionen.c"
int kontakt_hinzufuegen();
#endif /* KONTAKTVERZEICHNIS_H_ */
and this is kontaktfunktionen.c
#include <stdio.h>
kontakt[];
kontakt_hinzufuegen(){
int i = 0;
printf("Bisher sind %i Kontakte angelegt.",kontakt[i]);
kontakt[i++];
}
struct kontaktname{
char* name;
char* vorname;
};
struct kontaktanschrift{
char* strasse;
int hausnummer;
int plz;
char* ort;
char* land;
};
Where is my error?
You're not supposed to #include C files, that's not the proper way to organize your code.
You should compile the C files separately and then link them together, or compile them all at once with a single compiler invocation.
Do not #include anything in your header file. And do a #include "kontaktverzeichnis.h" in the kontaktfunktionen.c file.
As #StoryTeller commented, define your kontakt_hinzufuegen() as int kontakt_hinzufuegen() in the kontaktfunktionen.c file and return an int value from the function kontakt_hinzufuegen as for ex::
#include <stdio.h>
#include "kontaktverzeichnis.h"
// define the type for this array as below
int kontakt[];
int kontakt_hinzufuegen(){
int i = 0;
printf("Bisher sind %i Kontakte angelegt.",kontakt[i]);
kontakt[i++];
// Return an int value
return 0 ;
}
Your error is that in kontaktfunktionen.h you are including kontaktfunktionen.c. This will include all the definitions and declarations from kontaktfunktionen.c which are already declared when you use kontaktfunktionen.c
As others have said: You should not include .c files in your header files.

Using C Functions Defined in Shared Object Without Renaming Them

I have been reading the on-line book Basics of libuv and trying to rewrite them to work with both a static link and a dynamic link to the libuv library. I rewrote the watchers example (code below), but I had to "rename" the functions I retrieved from libuv.dylib to make it work, which means I had to write an entirely separate code path for the dynamic linking case. Can I somehow keep the same function names?
I want my code to look like this.
#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
#endif
int64_t counter = 0;
void wait_for_a_while(uv_idle_t *handle, int status) {
counter++;
if (counter >= 10e6)
uv_idle_stop(handle); // This function pointer must be a global variable
}
int main(int argc, char **argv) {
uv_idle_t idler;
// Initialize code needed for dynamically-linked library
#ifdef DYNAMIC
void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
// Set up pointers to functions defined in libuv.dyld ...
#endif
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for_a_while);
printf("Idling...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
// Clean up dynamically linked code
#ifdef DYNAMIC
dlclose(lib_handle);
#endif
return 0;
}
Currently, it looks like this.
#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
// Currently, I need to define function pointers with different names
// than the functions they call
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
uv_loop_t* (*udl)(void);
int (*uii)(uv_loop_t*, uv_idle_t*);
int (*uist)(uv_idle_t*, uv_idle_cb);
int (*uisp)(uv_idle_t*);
#endif
int64_t counter = 0;
void wait_for_a_while(uv_idle_t *handle, int status) {
counter++;
if (counter >= 10e6)
#ifdef DYNAMIC
uisp(handle);
#else
uv_idle_stop(handle); // This should be the only line remaining
#endif
}
int main(int argc, char **argv) {
uv_idle_t idler;
// Code path for dynamic linking case
#ifdef DYNAMIC
void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
// Retrieve symbol names from libuv.dylib
*(void **)(&uln) = dlsym(lib_handle, "uv_loop_new");
*(void **)(&ur) = dlsym(lib_handle, "uv_run");
*(void **)(&udl) = dlsym(lib_handle, "uv_default_loop");
*(void **)(&uii) = dlsym(lib_handle, "uv_idle_init");
*(void **)(&uist) = dlsym(lib_handle, "uv_idle_start");
*(void **)(&uisp) = dlsym(lib_handle, "uv_idle_stop");
uii(udl(), &idler);
uist(&idler, wait_for_a_while);
printf("Idling...\n");
ur(udl(), UV_RUN_DEFAULT);
dlclose(lib_handle);
// Code for static linking case
#else
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for_a_while);
printf("Idling...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
#endif
return 0;
}
Change:
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
/*...*/
into:
#ifndef DYNAMIC
#include <uv.h>
#else
#include <dlfcn.h>
/*...*/
Now, you can name your function pointer variables the same as the interfaces you want to call them as.
However, it is unclear why you need to do this at all. Normally, you just link your application with the dynamic library. You would only need to do what you are doing if you are experimentally changing the implementation of the dynamic library (treating it like a plugin).
In a comment, you mention that you need the definitions of structures in <uv.h>. Then to make my original proposal work, you would need to redefine those structures in the case of DYNAMIC, since you would not be using the header file. But, if the uv library ever changes, you would lose those changes and be forced to update your DYNAMIC version to match, which is an undesirable situation.
Another work around is to follow your original approach of defining different function pointer names, but then define macros to map the original function names to the function pointer names.
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
//...
#define uv_loop_new uln
#defin uv_run ur
//...
#endif

How should I organize this C project

I am doing this programming assignment in C. But I am confused as to how to organize it.
So, here is the situation. I have two tree implementations and declare their struct/includes/function prototypes and so on in two separate header files. Then I have two c source code for the two implementations. Now here comes the problem. I have one test c file (only one main function for running tests) for the ADTs of Trees. Since the two implementations are going to use the same test. How can I avoid making two copies of the same main.c file? when I include the header file of tree implementation1, I can do gcc Tree_implementation1.c main.c. But to do implementation2, I have to got back in the main source file and manually change the include to tree implementation2, and then I can use the same compilation command. How do I work around this to toggle between the two implementations with only one main.c?
Use the preprocessor and a constant that you can set on the command line:
In your main.c:
#ifdef TREE_IMPL1
#include "TreeImplementation1.h"
#else
#include "TreeImplementation2.h"
#endif
// ...
int main(int argc, char **argv)
{
#ifdef TREE_IMPL1
// code for testing TreeImplementation1
#else
// code for testing TreeImplementation2
#endif
}
When you compile, pass or omit TREE_IMPL1 on the command line, or set it in your IDE:
gcc -DTREE_IMPL1 main.c ...
Do your implementations have the same name? They shouldn't.
If (or when) they don't have the same name, you can just include both headers in main.c and test either one depending on some preprocessor directive.
//main.c
#include "Tree_implementation1.h"
#include "Tree_implementation2.h"
int main()
{
#ifdef TEST_FIRST
testFirstTree(); //declared in Tree_implementation1.h
#else
testSecondTree(); //declared in Tree_implementation2.h
#endif
return 0;
}
Another solution for your problem is using of dynamic interface.
Work the way like that:
#include "Imp_1.h"
#include "Imp_2.h"
typedef void (*TreeFunctionType1)(Tree,param);
typedef void (*TreeFunctionType2)(Tree);
typedef struct ITree
{
TreeFunctionType1 func1;
TreeFunctionType2 func2;
}ITree;
static ITree _Itree={0};
void SetImp(TreeFunctionType1 f1,TreeFunctionType2 f2)
{
tree.func1 = f1;
tree.func2 = f2;
}
/*Use only this functions in your Tests code*/
//{
void Func1(Tree tree,Param param)
{
(*_Itree.func1)(tree,param);
}
void Func2(Tree tree)
{
(*_Itree.func2)(tree);
}
//}
int main(int argc, char const *argv[])
{
SetImp(Imp_1_f1,Imp_1_f2);
TestCode();
SetImp(Imp_2_f1,Imp_2_f2);
TestCode();
return 0;
}

Resources