C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 06-16-2008, 08:19 AM   #1
Registered User
 
Join Date: Jun 2008
Posts: 4
preprocessor help

Hi,

I´m trying to create a routine to validate my casting. What I want to do is if my structure size is right put some code, if the code should report an error.
Does anyone knows how can I do this at compile time?
Code:
#define COMPILE_TIME_ASSERT(test, a) \
#if (test == 1) \
 *(char*)&(a)\
#else\
"Structure size error!"\
#endif

#define  BYTE(a)    COMPILE_TIME_ASSERT(sizeof(a) == 1, a)

int main
{
    char a,b;
    b = BYTE(a);
    BYTE(a) = a+1;
    return a;
}
Bruno
brunogon is offline   Reply With Quote
Old 06-16-2008, 08:25 AM   #2
Deathray Engineer
 
MacGyver's Avatar
 
Join Date: Mar 2007
Posts: 3,211
Try something like this in your #else construct:

Code:
#error "Structure size error!"\
Edit: Well, that is just for spitting out the error message. I'm not sure about the rest of your stuff.
__________________

Last edited by MacGyver; 06-16-2008 at 08:29 AM.
MacGyver is offline   Reply With Quote
Old 06-16-2008, 08:26 AM   #3
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
No, you can't. "sizeof()" is done later during the compile than the preprocessor, so you can't do that.

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
matsp is offline   Reply With Quote
Old 06-16-2008, 08:29 AM   #4
Technical Lead
 
QuantumPete's Avatar
 
Join Date: Aug 2007
Location: London, UK
Posts: 723
The Preprocessor is just a dumb search-and-replace tool. It doesn't evaluate the code in any way. f you need to validate a sizeof() you'll need to have the compiler do it for you.

QuantumPete
__________________
"No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
"Have you tried turning it off and on again?" - The IT Crowd
QuantumPete is offline   Reply With Quote
Old 06-16-2008, 09:27 AM   #5
Registered User
 
Join Date: Jun 2008
Posts: 4
So far, I think It is getting the sizeof correctly, the problem is if has any way to define my
#define COMPILE_TIME_ASSERT(test, a) with a preprocessor #if.

As the #if gives me an error, I also tryied use (test) ? *(char*)&(a) : "error"; despite it compiles okay, it add the whole code on the define and not just the *(char*)&(a) or "error"
brunogon is offline   Reply With Quote
Old 06-16-2008, 10:08 AM   #6
Mysterious C++ User
 
Join Date: Oct 2007
Posts: 14,099
I don't think this sort of thing can be done in C, or at least not easily.
However, it can be done easily in C++.
__________________
Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System
I dedicated my life to helping others. This is only a small sample of what they said:
"Thanks Elysia. You're a programming master! How the hell do you know every thing?"
Quoted... at least once.
Quote:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.
Elysia is offline   Reply With Quote
Old 06-16-2008, 10:13 AM   #7
Registered User
 
C_ntua's Avatar
 
Join Date: Jun 2008
Posts: 1,134
Quote:
Originally Posted by Elysia View Post
I don't think this sort of thing can be done in C, or at least not easily.
However, it can be done easily in C++.
How would it be done in C++ (curious, curious, don't really use C++)
C_ntua is offline   Reply With Quote
Old 06-16-2008, 10:20 AM   #8
Mysterious C++ User
 
Join Date: Oct 2007
Posts: 14,099
Psuedo code, but...
Something along the lines of:
Code:
int main()
{
    char mychar;
    int myint;
    char* c = safe_cast<char>(mychar); // Compiles
    c = safe_cast<char>(myint); // Won't compile
}

template<typename NewType, typename OriginalType>
NewType& safe_cast(Original& Data)
{
    STATIC_ASSERT(sizeof(NewType) == sizeof(OriginalType));
    return (NewType)Data;
}
This is dependant on boost's STATIC_ASSERT (or what it's called; can't remember 100%) macro.
There are more ways to do this, of course, but this is the easy way.

I haven't checked if this will compile, so it may contain a few errors, but the theory is sound.

And in you don't want to use boost, you can just the compiler to complain.
Something like:
Code:
int main()
{
    char mychar;
    int myint;
    char* c = safe_cast<char>(mychar); // Compiles
    c = safe_cast<char>(myint); // Won't compile
}

template<bool bFail>
struct dummy { static const bool bFail; };

template<>
struct dummy<true> { static const bool bFail = 'a'; }; // Causes a compile error about conversion from char to bool on purpose

template<>
struct dummy<false> { static const bool bFail = false; };

template<typename NewType, typename OriginalType>
NewType& safe_cast(Original& Data)
{
    dummy< sizeof(NewType) != sizeof(OriginalType) >::bFail;
    return (NewType)Data;
}
__________________
Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System
I dedicated my life to helping others. This is only a small sample of what they said:
"Thanks Elysia. You're a programming master! How the hell do you know every thing?"
Quoted... at least once.
Quote:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.

Last edited by Elysia; 06-16-2008 at 10:32 AM.
Elysia is offline   Reply With Quote
Old 06-16-2008, 10:21 AM   #9
Registered User
 
Join Date: Jun 2008
Posts: 1
A workaround I've used before is something like:

Code:
#define COMPILE_ASSERT(_cond)   typedef char _Dummy[(_cond)]
Then you'd use it like:

Code:
int main()
{
     COMPILE_ASSERT(sizeof(char) == 1);
}
You'd have to check if your compiler supports the definition of zero-element arrays (I remember some Linux compilers did). In which case, you'd redefine the macro to:

Code:
#define COMPILE_ASSERT(_cond)   typedef char _Dummy[(_cond) - 1]
Of course, you won't get a proper error message when the assertion fails, but eh.
Balbanes is offline   Reply With Quote
Old 06-16-2008, 10:24 AM   #10
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
Quote:
Originally Posted by brunogon View Post
So far, I think It is getting the sizeof correctly, the problem is if has any way to define my
#define COMPILE_TIME_ASSERT(test, a) with a preprocessor #if.

As the #if gives me an error, I also tryied use (test) ? *(char*)&(a) : "error"; despite it compiles okay, it add the whole code on the define and not just the *(char*)&(a) or "error"
You also can't put preprocessor commands in a macro (well, you can, but it doesn't do what you want). The preprocessor FIRST examines for #if, #include, #define. It then replaces the COMPILE_TIME_ASSERT() with whatever you define it as - so it will replace your macro with #if .... Then the compiler proper comes to work, and it says "Huh? What's this #if - I've never heard of that... "

So, you have to use regular if-statements to make the compiler see what you want. If it's even a little bit clever, it will then optimize away your test all together unless it's failing, and if it fails, then it will produce ONLY the code to perform your error message.

I presume Elysia is referring to the template meta-programming stuff you can do in C++, where templates ARE expanded at compile time when sizeof() and such is known to the compiler.

--
Mats

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
matsp is offline   Reply With Quote
Old 06-16-2008, 10:28 AM   #11
Mysterious C++ User
 
Join Date: Oct 2007
Posts: 14,099
Quote:
Originally Posted by matsp View Post
I presume Elysia is referring to the template meta-programming stuff you can do in C++, where templates ARE expanded at compile time when sizeof() and such is known to the compiler.
Indeed. It's potent stuff.
__________________
Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System
I dedicated my life to helping others. This is only a small sample of what they said:
"Thanks Elysia. You're a programming master! How the hell do you know every thing?"
Quoted... at least once.
Quote:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.

Last edited by Elysia; 06-16-2008 at 10:48 AM.
Elysia is offline   Reply With Quote
Old 06-16-2008, 10:45 AM   #12
Registered User
 
Join Date: Jun 2008
Posts: 4
Thanks everybody,

Unfortunately I can´t use C++ code, I was trying to do some decent cast validation, but I think it is not possible.
Tks again for your help
brunogon is offline   Reply With Quote
Old 06-16-2008, 11:11 AM   #13
Registered User
 
Join Date: Jun 2008
Posts: 4
Anyway, If I try implement this during execution, and not at the preprocessor, would it be possible? Any ideas?

I would need something that makes posbile to use it exactly as *(char*)&(a).
I mean a = safe_cast(b), safe_cast(b) = a

Cheers

Last edited by brunogon; 06-16-2008 at 11:13 AM.
brunogon is offline   Reply With Quote
Old 06-16-2008, 11:14 AM   #14
Mysterious C++ User
 
Join Date: Oct 2007
Posts: 14,099
It would be possible at runtime, yes. Perhaps you can use...
if (sizeof(a) != sizeof(b)) abort();
...type of macro.
It's runtime, but it's better than nothing.
(C++ can do it compile time.)
__________________
Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System
I dedicated my life to helping others. This is only a small sample of what they said:
"Thanks Elysia. You're a programming master! How the hell do you know every thing?"
Quoted... at least once.
Quote:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.
Elysia is offline   Reply With Quote
Reply

Tags
compile, preprocessor

Thread Tools
Display Modes

Forum Jump


All times are GMT -6. The time now is 10:25 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22