Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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) != sizeof(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.

like image 526
eckes Avatar asked Oct 05 '11 06:10

eckes


2 Answers

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.

like image 174
curiousguy Avatar answered Nov 07 '22 12:11

curiousguy


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.

like image 39
eran Avatar answered Nov 07 '22 10:11

eran