Hi guys,
I have a piece of code that I copied from another source but I don't understand what it means and the Keil compiler doesn't either.
The code looks like that:
#if _MSC_VER >= 1000 #define __CIFx_PACKED_PRE #endif typedef __CIFx_PACKED_PRE struct DRIVER_INFORMATIONtag { char abDriverVersion[32]; uint32_t ulBoardCnt; } __CIFx_PACKED_POST DRIVER_INFORMATION;
I get this error message for this typedef statement:
cifXUser.h(236): warning: #260-D: explicit type is missing ("int" assumed) cifXUser.h(236): error: #65: expected a ";"
And acutally I haven't seen a typedef like this before... in my opinion a typedef should look like something without the "__CIFx_PACKED_PER" part.
Can you help me in configuring the compiler right (so that it compiles that) and could you tell me, what it is about here?
Thanks a lot!!!
Strip the #__CIFx_PACKED_PRE word.
Or add a
#define __CIFx_PACKED_PRE
making the preprocessor strip that word on-the-fly.
You need to check Microsoft Visual C++ documentation to figure out what they intended to do with the additional __CIFx_PACKED_PRE attribute.
Just that the full source code must have had another #define line somewhere or some versions of Visual C++ must have had that symbol pre-defined. I would have expected the CIFx_PACKED_PRE symbol to be expanded to __packed or similar when building for some versions of VC++.
Maybe you are missing a
#include <stdint.h>
no, that didn't change anything :)
what does strip mean in this case? The adding of
somewhere before in the code, hasn't solved the problem..
sorry, that did help indeed. Thank you! I was wrong.
But what does it do: just doing a #define blabalba I always thought that defines have to be followed by a number or something...like that:
#define xyz 16
"I always thought that defines have to be followed by a number or something"
You need to go back to your 'C' textbook and review the chapter on #defines!
Some suggested resources here: blog.antronics.co.uk/.../12
It is perfectly valid (and, as seen here, quite common) to have a #define symbol that expands to nothing at all!
Some compilers have extra keywords outside the language standard.
So for some operating systems, you may have to use these extra keywords as attributes to get the compiler to generate special code - maybe for a calling convention used by the OS.
In that case, the preprocessor may check what environment the code is compiled for. If compiled for an environment where this extra attribute is needed, then the code has a
#if defined(SPECIAL_CALLING_CONVENTION) #define MY_CALLING_CONVENTION_KEYWORD __bloody_fast_call #else #define MY_CALLING_CONVENTION_KEYWORD #endif ... void MY_CALLING_CONVENTION the_function(void) { }
On an environment where SPECIAL_CALLING_CONVENTION is defined, the compiler will see:
void __bloody_fast_call the_function(void) { }
On an environment where SPECIAL_CALLING_CONVENTION isn't defined, the compiler will see:
void the_function(void) { }
If checking around, you could find Microsoft include files where function prototypes looks like:
WINBASEAPI DWORD WINAPI GetCurrentThreadId( VOID );
So WINBASEAPI and WINAPI can expand to target-specific extra goodies when needed.
And you might be able to find things like:
/* Define __cdecl for non-Microsoft compilers */ #if ( !defined(_MSC_VER) && !defined(__cdecl) ) #define __cdecl #endif /* Define _CRTAPI1 (for compatibility with the NT SDK) */ #ifndef _CRTAPI1 #if _MSC_VER >= 800 && _M_IX86 >= 300 #define _CRTAPI1 __cdecl #else #define _CRTAPI1 #endif #endif
In your case, the issue was a structure. In the general case, it's the compiler that "owns" the memory layout of a struct. So the compiler may have one or more specific attributes to allow a user to select a specific packing for the structure. Should it be packed for maximum speed, with potentially a lot of padding between fields to make sure that things match up depending on data type sizes and maybe even in modulo relation to processor cache line sizes.
Or maybe the compiler should pack all struct members to smallest size, with zero padding even if that makes all members larger than 1 potentially misaligned.
Or maybe the compiler has a pack attribute to select pack to 16-bit or 32-bit align.
Your sample code looks like it was written to take into account some such special packing instruction depending on what compiler that was used.
So if a define has only one argument the compiler will remove this in the code. That's good to know and yes: I will read my textbook again. It's has been a while since I looked into it last time. Thanks Per and Andrew!
One argument?
No #define <name> <expansion data>
or #define <name> (<arg>[,<arg>]) <expansion data>
A #define always has a name of the defined symbol. Then an optional list of arguments. Then what the #define should expand to - and it's allowed to have empty defines that does not have any expansion data.
Remember that #define is a preprocessor concept. It's a glorified search/replace that is done on-the-fly before the compiler processes the source code.
sorry: what I meant by 'argument' was <name>.
So what I actually wanted to state to verify my understanding was:
If there is just a name and no expansion data in the #define, then the compiler will just remove that name in the sourcecode while preprocessing.