diff options
author | Carl Shapiro <cshapiro@google.com> | 2011-06-22 11:45:37 -0700 |
---|---|---|
committer | Carl Shapiro <cshapiro@google.com> | 2011-06-22 11:45:37 -0700 |
commit | d2bdb57c9a3ceb5ac86060186cfe735a11f1e76e (patch) | |
tree | 48635d154094ee3443bfc94557e2b62291a669d5 /src/macros.h | |
parent | a2e18e1e77fc25c8260aad5daa267ababfcb65f6 (diff) | |
download | art-d2bdb57c9a3ceb5ac86060186cfe735a11f1e76e.zip art-d2bdb57c9a3ceb5ac86060186cfe735a11f1e76e.tar.gz art-d2bdb57c9a3ceb5ac86060186cfe735a11f1e76e.tar.bz2 |
Add a macro for sizing anonymous or locally defined arrays.
Change-Id: If7f7c7fb7b45d9f07a729aad978b26ffd88222d6
Diffstat (limited to 'src/macros.h')
-rw-r--r-- | src/macros.h | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/src/macros.h b/src/macros.h index be31e03..078628f 100644 --- a/src/macros.h +++ b/src/macros.h @@ -59,7 +59,7 @@ struct CompileAssert { // // One caveat is that arraysize() doesn't accept any array of an // anonymous type or a type defined inside a function. In these rare -// cases, you have to use the unsafe ARRAYSIZE() macro below. This is +// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is // due to a limitation in C++'s template system. The limitation might // eventually be removed, but it hasn't happened yet. @@ -71,6 +71,46 @@ char (&ArraySizeHelper(T (&array)[N]))[N]; #define arraysize(array) (sizeof(ArraySizeHelper(array))) +// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, +// but can be used on anonymous types or types defined inside +// functions. It's less safe than arraysize as it accepts some +// (although not all) pointers. Therefore, you should use arraysize +// whenever possible. +// +// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type +// size_t. +// +// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. +// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +#define ARRAYSIZE_UNSAFE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) + #define SIZEOF_MEMBER(t, f) sizeof(((t*) 4096)->f) #define OFFSETOF_MEMBER(t, f) \ |