How to check if bool already exists - c

I an developing a lib for use on an embedded platform. I have code in a header that is part of the lib with
typdef enum bool {false, true} bool;
If the lib user has already defined a type named bool, how can I code this so that my lib does not attempt to re-declare it?
Currently I have used #defines
#ifndef _BOOL
#define _BOOL
typedef enum bool{...
#endif
however this depends on a user that has bool defined also defining _BOOL
Is there a way of checking if types`with specific names already exist?
(Note this is a C Question, not C++, and neither I nor my assumed lib user is using stdbool, Ta)

You can't.
Your library probably should just define its own, distinct boolean type:
typedef enum { libname_false, libname_true } libname_bool;
Within your library implementation you could alias those to more convenient names as you desire.
Incidentally, you should not name preprocessor macros with leading underscores; those names are reserved for the compiler.

I would go a way you going now, supplying some kind of your_lib_config.h with #defines like HAS_BOOL_DEFINED or anything similar which affects your library configuration. So user will be responsible to adjust settings in config header before using your library.

Related

#undef not work as expected in my C program

I am writing linear list ADT as my practice in DS class. I use one header file, one function source code and a driver as a whole project. I defined macro "ELEMENT_TYPE" and "MAXSIZE" in the header file. My design is that I can #undef and immediately #define those two macros in the driver program to change "ELEMENT_TYPE" to any type the driver need.
If I put these code:
#undef ELEMENT_TYPE
#define ELEMENT_TYPE char
#undef MAXSIZE
#define MAXSIZE 50
into the header file after the #define, then in the driver program, the functions can be recognized properly(For example, insertion() 's second augment was "ELEMENT_TYPE", use those code above, IDE shows that insertion() receive a char augment in driver program.) However, if I put those codes into the driver below #include "foo.h", then IDE cannot recognize what augments the fuction should receive and use the initial definition of "ELEMENT_TYPE", in this case, int. Who know what was wrong in my program so that preprocessing directives don't work properly?
Here are the original codes:
driver.c
https://paste.ubuntu.com/p/6B76vmk6nN/
linear_list.c
https://paste.ubuntu.com/p/SHq4W5zkGM/
linear_list.h
https://paste.ubuntu.com/p/VY8vcgFD89/
PS:I am not native English speaker, so maybe there are some places I didn't express clearly. Point them out and I'll add more details if needed.
What it sounds like is happening is you're trying to #define these values in the driver in the hopes that they will stay defined in linear_list.c.
The problem is that these files are compiled separately and then linked. The #defines placed in driver.c cannot change those found in linear_list.c.
In order to have the effect I think you would like, you will need to change these values in linear_list.h. This is the best way to do this because that header is included in both the source files, and will presumably be #included in any file that works with the functions defined in linear_list.c. Please bear in mind that in order to see a change in the behavior of your program you will need to recompile not only driver.c but linear_list.c after changes to linear_list.h have been made.
As a side note, you should generally #include local headers like linear_list.h after you #include global headers like stdio.h and stdlib.h. In linear_list.c either of those headers could overwrite the values you've used in linear_list.h, if those identifiers are used. They look like they could be common enough, that it's not implausible that some header may use them, so it may be worthwhile to use a more unique identifier in the future. Which leads me to my final point: using #undef on these identifiers without checking if they're used somewhere else could lead to some problems, so you should generally check with #ifndef.
Hope that helps. If I've misunderstood please correct me.
EDIT: Clarification, additional information, credit to the other answer for reminding me of some important practices.
Macros in source code are replaced with the macro definition in effect at that point where the macro is used in the source code. So function declarations using ELEMENT_TYPE use the macro definition that most recently precedes the declaration. Changing the macro later will not change the function definition.
An alternative is to define ELEMENT_TYPE in the header only if it is not already defined:
#if ! defined ELEMENT_TYPE
#define ELEMENT_TYPE char
#endif
Then a source file can do either of:
Do not define ELEMENT_TYPE itself. When the header is included, the default type of char will be used.
Define ELEMENT_TYPE, then include the header. If desired, #undef ELEMENT_TYPE afterward. The type the source file provides in ELEMENT_TYPE will be used.
The driver and the program that uses it must use the same type. You cannot compile the driver using one type and the program using another. Compiling the program with a different type will not change the driver.

Howto handle typedefs without include headers in headers

As for working on a larger project, I want to throw in some own types (e.g. myType). The "rushing in"-approach would be, to put those typedefs into an header (lets say myType.h), together with a bunch of functions working on those types.
If I use the new type somewhere, I include myType.h to my source-file. Fine.
But if I want to use the new type somewhere as an argument in a function-signature, I need to include the myType.h to the header of the module containing the function. With one or another typedef, this seems to be okay for me, but the more types I have, the more includes in headers I need, possible including further header, while using type including other own types. This is resulting in what I call "dependency hell".
Is there a clever, stylish, best practice, what-so-ever way to solve this dilemma?
I'm aware of the possibility to pass those types as void-pointer, casting them back inside the function, but then I loose important type-checking from the compiler.
Furher, extern is considered worst-practice around here..
EDIT:
In detail:
myType.h:
#include "otherType.h"
typedef struct {
char Name[32];
int Size;
otherType someType;
} myType;
processSomeHow(myType _myType, int NewSize);
otherType.h
#define SOME_CONST 32
typedef struct { [...] } otherType;
someModule.h:
#include "myType.h"
int specialProcessSomeHow(myType _myType);
someModule.c:
int specialProcessSomeHow(myType _myType)
{
int Size = 64;
return(processSomeHow(_myType, Size));
}
Now I include otherType.h indirectly to someModule.h, even worse, I include it to every module, that includes someModule.h. Now I have a SOME_CONST everywhere and it's hard to figure out, from where it comes. I have to maintain two include trees.
like in the gtk library you can use one headfile and split it on your needs.
type.h
- myType.h
-- someType.h
- otherType.h
- List item
and on your CONST-Problem:
If you just need it for one c.file. Don't use them in HeaderFile.
And you could name them like "MY_TYPE_SOME_CONST" or "OTHER_TYPE_SOME_CONST";
//EDIT:
to make it clear: just add 'this.h' file and name it.
#ifndef TYPE_H_
#define TYPE_H_
#include myType.h
#include someType.h
#include otherType.h
#endif /* TYPE_H_ */
now you can use "#include this.h" for each file you need your types.
(this.h is not real, name it to something unique)
You can (and probably should) use forward declarations for your custom types. See details here: typedef stuct with forward declaration in C
Your interfaces (the headers) should have incomplete types (i.e. pointers to your custom types) and inside the source code (c files) you should include the My_Type.h.
You're worrying unnecessarily : There is no 'dependency hell', precisely because you are giving the compiler all the information it needs to do it's job.
Here's my rules for this:
Always, always use header guards.
Every .h file should
explicitly #include every other .h file it needs in order to compile,
and no more.
So if b.h uses a type from a.h, then b.h must #include "a.h". If b.c uses functions from a.h, but b.g doesn't use types from it, then b.c should #include a.h.
There's no need for extern keyword on functions in .h files, because IIRC modern compilers deduce this correctly.
Using extern for global variables may well be frowned on, with good
reason.
Cluttering of global namespace. C++ namespaces address this, but in C you have to use naming conventions for all global types, functions and #defines. Pick a convention that works for you : I've seen teams successfully use a LETTER-DIGIT-DIGIT prefix for every source file, so foo.h might become (for example) B04_foo.h, and all functions/types get the same B04_ prefix. It's a bit crude, but it works. As I say, pick one that works for you.

cant re-def enum type def

I have code for bool typedef
typedef enum bool {
false,
true,
} bool;
in two headers files if it is not included in the ultimate parent header file, child C files cannot, of course, use type bool, though children of the lesser header file that also defines it can.
However if I define it in the ultimate parent header file then the lesser header file definition errors with "bool has already been declared in the current scope"
I need a solution for the lesser header where it may be included on a project that may or may not have already defined bool... What is the best way to do this??
Ta
First of all, if you're working with a C99 compiler or later, there's already a standard Boolean type defined in stdbool.h.
Secondly, you can usually avoid testing against true and false values directly, and I've found over the years that this actually leads to code that's a little easier to read and less error-prone (that's just a personal opinion, though -- YMMV).
The immediate solution is to surround your typedefs with an include guard:
#ifndef BOOL_DEFINED
#define BOOL_DEFINED
typedef enum bool {
false,
true
} bool;
#endif
This will keep the type from being declared more than once. However, as you've discovered, putting the same type definition in two different headers is a recipe for heartburn. It would be better to put the definition in its own header file (with the include guards as shown above), and then include that file where necessary.
I'd factor this and any other shared definitions out into a types.h header which is included by each of your other headers.
Alternatively, you could do something like
#ifndef BOOL_DEFINED
#define BOOL_DEFINED
typedef enum bool {
false,
true,
} bool;
#endif
in both headers.

Compile time checking existence of stdint.h

I'm working with legacy embedded C code which defines the types uint8_t, uint16_t and uint32_t in a header file using the typedef keyword.
For discussion, let us say the file typedefs.h contains these definitions.
In my new C source module, I include stdint.h. I also include other header files which include typedefs.h somewhere in the hierarchy. As expected, the compiler complains about multiple defined symbols.
I would like to modify the legacy file typedefs.h so that it only declares the uint*_t types if either stdint.h is not included or better if the uint*_t types are not defined.
My understanding is that #ifndef cannot be used since typedef is not a preprocessor directive.
So how do I tell the compiler to not define the uint*_t if they already exist (or if the stdint.h is already included)?
Note: this would be easy if the C specification defined standard include guard definitions for the header files.
FWIW, I am using Green Hills compiler, 4.24, for an ARM9 processor.
I beleive that the stdint.h should also be defining a macro for the limits of the types that it defines. You should be able to test for those using a #ifdef and the like.
#ifndef UINT32_MAX
typdef ... uint32_t;
#define UINT32_MAX ...
...
#endif
Edit: Originally used UINT32_MIN, but as Jens Gustedt poited out this is the one combination of signed/unsigned and min/max that doesn't occur.
Just fix the legacy header to always include stdint.h to get these types, remove the duplicate definitions, and provide a drop-in file stdint.h for broken systems that lack it.
If you're on a UNIX system, then you should back-up a step and use a configuration package like autoconf(1) or automake(1). It's designed to handle problems like this.

Managing redundant typedefs from multiple vendors

What are some of the best ways to manage redundant typedefs used for platform independence from multiple middleware (operating systems, protocol stacks) vendors in the C programming language.
e.g.:
target.h
/* inclusion lock etc */
typedef char CHAR;
typedef unsigned char BYTE;
typedef unsigned short int WORD;
/* ... more of the same ... */
OS_types.h
/* inclusion lock etc */
typedef char CHAR;
typedef unsigned char BYTE;
typedef unsigned short int WORD;
/* ... more of the same ... */
At some point the compiler recognizes that it has two redundant typedef symbols and bails out with an error because this is simply not allowed by definition in C.
One possible way to do this without modifying the vendor's header would be to use the preprocessor with some header wrappers, e.g.
mytypes.h
#define BYTE VENDOR1_BYTE
#include <vendor1/types.h>
#undef BYTE
#define BYTE VENDOR2_BYTE
#include <vendor2/types.h>
#undef BYTE
typedef unsigned char BYTE;
This would result in the vendor's code generating different typedefs but hopefully mapped to the same actual type (unsigned char in the example). If the vendors are using different underlying types for the same type names then the method will likely not work.
That's a toughie. If I had to do something, I'd probably hold my nose and modify the third-party header-files -- possibly using macros to obtain conditional compilation of the offending typedefs.
Good luck.
If the vendor is responsive to feedback, you could beg them to move those generic type definitions into a separate file, e.g. types.h. If they're isolated in a separate file, it's much easier to manage. The solution could be as simple as removing their types.h and adding your own project-specific types.h which can do whatever it needs to do in your project.
Even better, beg them to use the standard C typedefs in stdint.h, i.e. uint16_t.
Otherwise, I'd suggest a modification to the vendor header files, done as cleanly as possible so it's easy to re-do when they next release code. Of course this all goes in your VCS so you can track exactly what changes you made!
One approach, although it could be a lot of work, is to build your own "wrapper" layers which provide only the functionality you need from each of the middleware vendors. If you keep each wrapper in its own compilation unit (.c file) that's the only place you'll need to refer to the vendor's header file. That gives you a way to prevent the conflicting types from "leaking" into your application, as you can use your own typedefs and translate them to the vendor-specific types in the wrapper.
As Steve suggested, modifying the header files might be the best solution, depending on how often the vendor ships new versions of their stuff. The overhead could get pretty high.
If you have the option to use C++ compilation for your own code (even if it is essentially C code) you could create namespace wrappers thus:
vendorA_target.h
namespace vendorA
{
extern "C"
{
#include <target.h>
}
}
vendorB_OS_types.h
namespace vendorB
{
extern "C"
{
#include <target.h>
}
}
Then in your own code. include these headers in place of the originals, and use scope-resolution, or if you are certain that types with the same name have identical or compatible definitions, simply us a using directive:
using vendorB::WORD
WORD timeout = 100 ;
vendorA::WORD x = 0xffff ;
Note that the extern "C" wrappers are not necessary if the headers already have them internally in __cplusplus macro conditionals - but it won't hurt.
Using C++ to compile C code imposes no overhead, but it does have stricter type comformaty checking, which while good for your code quality, may cause other headaches; especially if the third-party headers contain code that is invalid as C++. If the headers already have extern "C" declarations in __cplusplus macro conditionals, then they are already intended to be "C++-ready" and you may not have any such problems.
Unfortunately this method will not solve the problem of preprocessor macros with the same name. If you have that problem, you may have to #undef the macros from one header before including the other, or modify the headers.

Resources