How do I ensure that two types have the same size?
In my code, I want to ensure that sizeof(a) == sizeof(b)
.
First approach was to let the preprocessor do the checking:
#if (sizeof(a) != s开发者_如何转开发izeof(b))
# error sizes don't match
#endif
which doesn't compile because of fatal error C1017: invalid integer constant expression
. Okay. Understand.
Next try:
if(sizeof(a) != sizeof(b)){
printf("sizes don't match\n");
return -1;
}
Which results in a warning: warning C4127: conditional expression is constant
.
Now, I'm stuck. Is there a warning-and-error-free way to make sure that the two structs a
and b
have the same size?
Edit: Compiler is Visual Studio 2005, Warning level is set to 4.
Bad array size
// make sure sizeof(a) == sizeof(b): int size_must_match[sizeof(a) == sizeof(b)]; // will fail if sizeof(a) == sizeof(b) evaluates to 0 // might produce warning: 'size_must_match' is not used // to suppress "'size_must_match' is not used", try: size_must_match[0]; // might produce warning: "statement has no effect"
or
typedef int size_must_match[sizeof(a) == sizeof(b)];
Bad compile-time arithmetic
In C++ is guaranteed that these constant expressions are evaluated by the compiler at compile-time, and I believe the same holds in C:
// make sure sizeof(a) == sizeof(b): 1 / (sizeof(a) == sizeof(b)); // might produce warning: "statement has no effect" int size_must_match = 1 / (sizeof(a) == sizeof(b)); // might produce warning: 'size_must_match' is unused assert (1 / (sizeof(a) == sizeof(b))); // very silly way to use assert!
Switch (just for fun)
switch (0) { // compiler might complain that the // controlling expression is constant case 0: case sizeof(a) == sizeof(b): ; // nothing to do }
You get the idea. Just play around with this until the compiler is 100 % happy.
The first case is explicitly forbidden according to #if
documentation:
The expression cannot use sizeof or a type-cast operator.
As for the warning, you can either ignore it (because you know your code is ok), disable it using a #pragma
, or just take the condition out of the if
:
bool sizeMatch = (sizeof(a) == sizeof(b));
if (!sizeMatch){
printf("sizes don't match\n");
return -1;
}
Edit: since disabling the error seems to have drawn some attention, here are a couple of ways to achieve that using #pragma warning
:
#pragma warning (push)
#pragma warning (disable: 4127)
if(sizeof(a) != sizeof(b)){
#pragma warning (pop)
// ...
The pop could obviously be done further down the code. Another option could be:
#pragma warning (disable: 4127)
if(sizeof(a) != sizeof(b)){
#pragma warning (default: 4127)
Which will turn the warning back on without pushing and popping.
Either way, this code does look ugly. IMO, just using a bool
to get the result of the sizeof
comparison (as my first snippet shows) would be the cleanest solution.
#include <stdio.h>
struct tag {
int a;
};
main() {
struct tag a,b;
if(sizeof(a) != sizeof(b))
printf("not");
else
printf("same");
}
this programs works fine without any warning...!!!
While it is possible to play hide and seek with the compiler and hide the constant conditional in places the compiler cannot see it, it's not the best way to suppress warnings. It will only make the code seem unnecessarily obscure for the next person who is going to maintain it.
If you need to suppress compiler warnings, please be explicit about it. In Visual Studio 2005, you are best off using pragmas:
http://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx
精彩评论