I am new to c, and I have some been given some source code that someone else has written that was compiled on windows.
After trying to make in compile on linux I have errors because linux doesn't support DWORD, WORD, AND UINT32. I have 6 files for example. A.h, A.c, B.h, B.c, C.h, C.c. These keyword are in all the files.
So I am thinking of 2 possible solutions. Which is better #define or typedef.
1)
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned int UNINT32;
2)
#define DWORD unsigned long
#define WORD unsigned short
#define UINT32 unsigned int
For the second part I am wondering where should I put these declarations. Should they go in the header files, or should they go in the source files?
For example should I do something like this in the header files, or in the source files?
#ifdef WIN32
/* windows stuff */
#else
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned int UNINT32;
#endif
Many thanks for the above suggestions,
You have found the solution yourself:
#ifdef WIN32
/* windows stuff */
#else
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned int UNINT32;
#endif
Put this in a separate header file (typedefs.h) and include it from everywhere. Typedef are always preferred over pre-processor macros.
My recommendation: Do not use DWORD, WORD or other Win32 types. I usually prefer to use C99 standard types: uint_t, int_t or uint16_t, uint32_t
Typedefs are definitely nicer. #defines are preprocessor macro's and can have unintended consequences, because basically the C preprocessor performs a global search-and-replace for defines. Typedefs are instructions to the compiler, and much better suited for what you want to do.
typedef would be better in this instance because #define is just a generic mechanism but typedef is for defining types which is what you are doing.
I would say put your code:
#ifdef WIN32
/* windows stuff */
#else
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned int UNINT32;
#endif
into a new header file (with #define guards/#pragma once), then include that from the header or source files as necessary.
Using a typedef turns the result into an actual type that gets put into the syntax tree. (In other words, the compilers knows about it and recognizes it as a part of the language.)
#define, in contrast, is just a text-substitution. So the compiler never gets to know about it, it instead just sees whatever it is that gets substituted. This can make finding compile errors harder.
For your case, I would probably recommend typedef. #define has it's place, but I can't see any reason why you wouldn't want to use typedef here.
Be aware that other libraries may have defined these types, so you may have collisions. If you really want to be cross-platform, you might think about defining types with your app's namespace somehow. Like
myapp_dword
myapp_word
in order to minimize collisions with other libraries.
Finally, I would actually recommend against the entire approach you are taking. If at all possible, it is best to use only the typenames defined in the language and in the C standard library (like size_t, etc.) Your code will be more portable, and you will have less headaches.
Related
I'm writing a Chip-8 emulator in C, and my goal is to have it be compatible with as many different operating systems, new and old as possible I realize that a lot of different types for representing exact bit widths have been added over the years, so is something like this reasonable to both create a shortcut (so I don't have to write lots of unsigned chars/longs) and account for compilers that already have the numbers defined? If not, is there a better/more efficient way to do this?
#ifdef __uint8_t_defined
typedef uint8_t uchar;
typedef int8_t schar;
typedef uint16_t ushort;
typedef int16_t sshort;
#else
typedef unsigned char uchar;
typedef signed char schar;
typedef unsigned short ushort;
typedef signed short sshort;
#endif
You shouldn't make any assumptions on the sizes of the primitive types. Not even that char has 8 bits. Check this discussion:
What does the C++ standard state the size of int, long type to be?
I think standard integer types are pretty well-supported. If you don't have stdint.h, then your chances of cross-compatibility seem very dim to me. Expecting stdint.h to be available for the compiler seems like a reasonable pre-condition.
Yes, this is a very good idea! Never assume sizes for primitive types. If you are writing portable code this is a must for maintainability! This little trick will save tons of time and will help create a good foundation for maintaining a portable code base.
The overall idea is reasonable - write portable code. OP's approach is not.
__uint8_t is not defined by the C spec. Using that to steer compilation for portable code can lead to unspecified behavior. Better to use ..._MAX definitions.
Code is creating types based on fixed width types on one platform and non-specified widths on another. Not a good plan. Where code needs fixed width types, use fixed width types like uint8_t, etc. Where code wants to use short-hand uchar for unsigned char, etc., use a #define uchar unsigned char or better typedef unsigned char uchar;.
Attempting to create portable integer code without <stdint.h> is folly. Even compilers that do not natively have the file have on-line look alikes easily findable.
If user still wants to create uchar and friends like originally posted, suggest the more portable:
#include <stdint.h>
#ifdef INT_LEAST8_MAX
typedef uint_least8_t uchar;
#else
typedef unsigned char uchar;
#endif
#ifdef INT_LEAST16_MAX
typedef uint_least16_t ushort;
...
I define below data type:
typedef int MyInt;
Then I hope to define a new data type based on size of MyInt, something like below code, but I can't find a solution for it.
#if sizeof(MyInt) == 2
typedef long MyLong;
#else
typedef short MyLong;
#endif
Could anybody help?
It's not the preprocessor's job to evaluate sizeof, that's done by the compiler which is a later stage in the process. Evaluating sizeof needs deep C knowledge that the preprocessor simply doesn't have.
You could (in theory) consider the preprocessor as a separate step, that does text only transforms, in effect converting "foo.c" to "foo-preprocessed.c". The latter file won't have any #include or #ifs left, they're all evaluated and replaced by the preprocessor. The actual compiler never sees them.
You should consider using <stdint.h> and the known-precision types (uint16_t and friends).
You could use the values of macros such as UINT_MAX to determine the size of the underlying type.
You can use UINT_MAX - it can give you a clue about the size of integer.
#if (UINT_MAX <= 65536)
typedef long MyLong;
#else
typedef short MyLong;
#endif
New-enough GCC (I think 4.3) has predefined identifiers like __SIZEOF_LONG__, but it is simpler to just use the constants in limits.h as suggested by others.
Although I and the C preprocessor are sworn enemies, we sometimes need each other ;). So I would propose:
#if SIZEOF_MYINT == 2
# define MYLONG_T long
#elif SIZEOF_MYINT == 4
# define MYLONG_T short
#endif
typedef MYLONG_T MyLong;
Somewhere else (in a global config header file) you have your architecture dependent
#define SIZEOF_MYINT 2
I have a situation where two of my header files require the data structures defined in either one, i.e. no matter which order you include them it won't compile
however, one of the problem data structures only contains pointers to the data structure declared in the other header file so I would have though that technically it doesn't need to know at this point how big the data structure is so it shouldn't be complaining
A simplified example of what I mean is outlined below. I would have thought that the array of modes in Library doesn't need to know how big a Mode is, only how big a pointer to a Mode is therefore the compiler shouldn't complain if it hasn't yet seen the declaration of Mode in the other header file.
header_1.h
typedef struct
{
Mode **modes;
} Library;
header_2.h
typedef struct
{
int number;
char *name;
} Mode;
It doesn't need to know the size, but it must have seen a declaration. A forward declaration
typedef struct Mode Mode;
before the definition of struct Library suffices.
As currently written, your example does not show the mutual cross-referencing that you mention in the question.
The compiler must be told something about each type it uses. You could use in header_1.h just:
typedef struct Mode Mode;
typedef struct
{
Mode **modes;
} Library;
That would make it compile, at least. The compiler doesn't need the details, but it does need to know that Modes is a type.
Edit:
Note that header_2.h should be modified for this to work. You have to ensure that each typedef appears just once. After you have the typedefs in place, you specify the structure content (definition) once, and you omit the keyword typedef and the typedef name from the structure definition. And you have to decide on exactly the cross-references will be managed. For example, should header_1.h include header_2.h anyway.
I don't remember encountering a case where I really needed mutually referencing structures (in quite a long time programming — long enough that I could have forgotten a example). I do now remember a case of structures mutually referencing each other; it was in a version of make originally written for Minix. I still regard such a requirement as somewhat 'pathological' (or, if you prefer, as a 'code smell') and as something to be avoided whenever possible. If you really must manage it, then the section below explains how I'd go about doing it (and more or less how the make program did go about it).
Mutually-referencing structures
If you truly have two mutually referencing structures, you should (re)consider why you think two headers are better than one. If you still need two headers, you use an idiom like:
header_1.h
#ifndef HEADER_1_H_INCLUDED
#define HEADER_1_H_INCLUDED
#ifndef TYPEDEF_MODE
#define TYPEDEF_MODE
typedef struct Mode Mode;
#endif
#ifndef TYPEDEF_LIBRARY
#define TYPEDEF_LIBRARY
typedef struct Library Library;
#endif
struct Library
{
...
Mode **modes;
...
};
#endif /* HEADER_1_H_INCLUDED */
header_2.h
#ifndef HEADER_2_H_INCLUDED
#define HEADER_2_H_INCLUDED
#ifndef TYPEDEF_MODE
#define TYPEDEF_MODE
typedef struct Mode Mode;
#endif
#ifndef TYPEDEF_LIBRARY
#define TYPEDEF_LIBRARY
typedef struct Library Library;
#endif
struct Mode
{
...
Library **liblist;
...
};
#endif /* HEADER_2_H_INCLUDED */
The repeated typedef 'detection' code is not nice; a single header is better, in my estimation. However, you can include header_1.h and header_2.h above in either order and it should compile.
I believe this is happening because "Mode" is a type defined using typedef and its not the name of the struct. You will either need to explicitly forward declare it or you can try using the code structured as follows:
header_1.h
typedef struct
{
struct _Mode_t **modes;
} Library;
header_2.h
typedef struct _Mode_t
{
int number;
char *name;
} Mode;
I'm compiling a C program which includes sybdb.h and I get the error "two or more data types in declaration specifiers" at the typedef line below (and sybdb.h is a standard file, not one of mine).
#if !defined(_WINDEF_) && !defined(_WINDEF_H) && !defined(DOS32X)
typedef int BOOL;
#endif
It appears that there is some kind of a conflict with another library I am including, but have no idea what the error means or how to fix it. Help?
Most likely another header (or your implementation of C itself) has done something like:
#define BOOL unsigned char
so that your compiler is seeing:
typedef int unsigned char;
By way of experiment, when I compile the code:
#define XYZZY unsigned char
typedef int BOOL;
int main (void) {
return 0;
}
it works fine but, when I change that first line to #define BOOL unsigned char, I get the exact same message you see:
qq.c:2:17: error: two or more data types in declaration specifiers
qq.c:2:5: warning: useless type name in empty declaration
To confirm this, you can compile only the pre-processor phase to see what that code really looks like to the compiler phase.
This depends on the compiler, of course, gcc -E is the option you would use for gcc.
Fixing it is another matter. You may well have to change one of the alias types to BOOL1 or something incredibly ugly like that. That's likely to be a larger change since I imagine it would be used quite a bit.
You may be able to get away with simply ensuring both subsystems use the same definition of BOOL but it will still take quite a bit of analysis to confirm that this won't have adverse side effects.
To test (and even possibly implement) this fix, you can change the #if statement to something like:
#ifndef SKIP_BOOL_DEF
#if !defined(_WINDEF_) && !defined(_WINDEF_H) && !defined(DOS32X)
typedef int BOOL;
#endif
#endif
and then compile your code with gcc -DSKIP_BOOL_DEF (or equivalent) to ensure the typedef isn't done. It would then use your (hopefully compatible) system definition.
How does one define different types of ints?
I have the following
struct movCommand
{
uint8_t type;
uint8_t order;
int16_t height;
uint16_t distance;
int16_t yaw;
};
and need to define these according to the types they are.
What is the correct syntax for #define when selecting the type for the define?
EDIT :
It looks like my question has been misunderstood.
I want to do this #define LANDING_COMMAND "2"
But I want to set the type of the landing command because it needs to be int16_t
You do not use #define for this. You #include <stdint.h>
Rather than using the #define directive, I'd use a typedef, which is how the standard-library would define them inside of <stdint.h> (at least on a C99-compatible platform). If you look in that header, you'll see how they're defined specifically on their platform. Typical typedefs will be:
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef int int32_t;
//... etc., etc.
There's a lot more typedef's defined inside the header file, including 64-bit types, etc.
If you are working with C99, you can use the typedefs from <stdint.h> or <inttypes.h> (and <inttypes.h> might be available even if <stdint.h> is not - in non-C99 compilers).
If they are available (they usually are), all the types you show will be provided by those headers.
In general, a typedef is preferable to a #define.
With regards to your new question, the #define is replaced literally with the text you provide. So
#define LANDING_COMMAND "2";
Will replace all uses of LANDING_COMMAND with "2"; in the program text. This is probably not what you want.
First, preprocessing directives are not part of the C language, they're part of the preprocessor. Since they're not part of C, they're not statements, so they don't end with ;. If you leave that in, it will likely cause problems if you intend to do things like func(LANDING_COMMAND);.
Second, "2" is of type char *, which is not convertible to int16_t with any safety. You need to use a literal 2 for the numeric value.
Lastly, to make it type int16_t, you'll need to provide either a cast (((int16_t)2)) or use the macro INT16_C(2) which expands to a literal with the appropriate suffix to make it of size (and type) int16_t. I recommend the latter, but the former should work. The macro INT16_C(2) could be used, but it expands to a literal (with the appropriate suffix) of type int_least16_t, which is close but no cigar. stdint.h only provides macros to make integer constant literals of the [u]int_leastN_t types and the [u]intmax_t types, not more generally for the [u]intN_t or [u]int_fastN_t types. Why they don't is beyond me.
include stdint.h gives you 8, 16, 32, and 64 signed and unsigned.
http://en.wikipedia.org/wiki/Stdint.h
You can't do what you describe. Other answers have indicated workarounds. As for your specific question, from the MSDN site:
Expressions must have integral type
and can include only integer
constants, character constants, and
the defined operator.
The expression cannot use sizeof or a
type-cast operator.
#define doesn't have a type. It's exactly the same as find/replace in your editor.
You can do
#define LANDING_COMMAND 2
...
my_movCommand.yaw = LANDING_COMMAND;
The compiler will do the right type conversions for you, but if you insist on a type int16_t then
#define LANDING_COMMAND ((int16_t)2)