Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Getting the size of a type in a macro conditional

Tags:

c++

macros

sizeof

Is there some way to do something like this in c++, it seems sizeof cant be used there for some reason?

#if sizeof(wchar_t) != 2
#error "wchar_t is expected to be a 16 bit type."
#endif
like image 339
Fire Lancer Avatar asked Aug 02 '09 15:08

Fire Lancer


People also ask

Can sizeof be used in macro?

The sizeof in C is an operator, and all operators have been implemented at compiler level; therefore, you cannot implement sizeof operator in standard C as a macro or function.

Can I #define in a macro?

(2) However, you cannot define a macro of a macro like #define INCLUDE #define STDH include <stdio. h> .

Is sizeof a macro in C?

In c, we are using the sizeof() for getting the size of the datatypes. So how it is defined. It is a macro or a function.

What is sizeof () in C operator function macro?

Answer: sizeof is a unary operator in the programming languages C and C++. It generates the storage size of an expression or a data type, measured in the number of char-sized units. Consequently, the construct sizeof is guaranteed to be 1.


7 Answers

No, this can't be done because all macro expansion (#... things) is done in the pre-processor step which does not know anything about the types of the C++ code and even does not need to know anything about the language! It just expands/checks the #... things and nothing else!

There are some other common errors, for example:

enum XY
{
  MY_CONST = 7,
};

#if MY_CONST == 7
  // This code will NEVER be compiled because the pre-processor does not know anything about your enum!
#endif //

You can only access and use things in #if that are defined via command line options to the compiler or via #define.

like image 169
mmmmmmmm Avatar answered Sep 28 '22 17:09

mmmmmmmm


The preprocessor works without knowing anything about the types, even the builtin one.

BTW, you can still do the check using a static_assert like feature (boost has one for instance, C++0X will have one).

Edit: C99 and C++0X have also WCHAR_MIN and WCHAR_MAX macros in <stdint.h>

like image 26
AProgrammer Avatar answered Sep 28 '22 17:09

AProgrammer


I think things like BOOST_STATIC_ASSERT could help.

like image 44
EFraim Avatar answered Sep 28 '22 18:09

EFraim


Wouldn't you get basically what you want (compile error w/o the fancy message) by using a C_ASSERT?

#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
like image 42
gatorfax Avatar answered Sep 28 '22 17:09

gatorfax


sizeof() is a runtime compile-time function. You cannot call that in a preprocessor directive. I don't think you can check the size of wchar_t during preprocessing. (see Edit 2)

Edit: As pointed out in comments, sizeof() is mostly calculated at compile time. In C99, it can be used at runtime for arrays.

Edit 2: You can do asserts at build time using the techniques described in this thread.

like image 20
nagul Avatar answered Sep 28 '22 19:09

nagul


char _assert_wchar_t_is_16bit[ sizeof(wchar_t) == 2 ? 1 : -1];
like image 23
Adrian Panasiuk Avatar answered Sep 28 '22 19:09

Adrian Panasiuk


I've developed some macros that will effectively allow you to use sizeof within a macro condition. They're in a header file that I've uploaded here (MIT license).

It will permit for code like this:

#include <iostream>
#include "SIZEOF_definitions.h"

//You can also use SIZEOF_UINT in place of SIZEOF(unsigned, int)
// and UINT_BIT in place of SIZEOF_BIT(unsigned, int)
#if SIZEOF(unsigned, int) == 4
int func() { return SIZEOF_BIT(unsigned, int); }
#elif SIZEOF(unsigned, int) == 8
int func() { return 2 * SIZEOF_BIT(unsigned, int); }
#endif

int main(int argc, char** argv) {
  std::cout SIZEOF(unsigned, long, int) << " chars, #bits = " << SIZEOF_BIT(unsigned, long, int) << '\n'
         << SIZEOF(unsigned, int)       << " chars, #bits = " << SIZEOF_BIT(unsigned, int)       << '\n'
         << SIZEOF(int)                 << " chars, #bits = " << SIZEOF_BIT(int)                 << '\n';
  std::cout << func() << std::endl;
  return 0;
}

Note the commas within SIZEOF(unsigned, long, int).

like image 26
Matthew K. Avatar answered Sep 28 '22 17:09

Matthew K.