1

I'm looking for a macro similar to this: Compile-time assertion to determine if pointer is an array

The basic problem is sizeof(x) == 8 always (on a 64-bit compile) if x is a pointer, while it could be many different values if x is a statically allocated array.

But an array decays to a pointer, and an array could coincidentally have 8 bytes (e.g. a char array sized to 8 or an int array sized to 2).

The macro I would like is: #define arr(x) x, sizeof(x)

The idea is to use in function calls, for example:

char str[1024];
.
.
func(str, sizeof(str));

becomes:

char str[1024];
.
.
func(arr(str));

The problem is it's easy for str to be a pointer rather than true array. For example, you could mix up identifiers, or have a malloc()'d array.

What should happen is if str is not a statically allocated array, then there is a compile error. For example:

char str[1024];
func(arr(str)); /* works */
.
.
size_t size = 1024;
char *buf = malloc(size);
func(arr(buf)); /* compile error */

... and you must replace with:

size_t size = 1024;
char *buf = malloc(size);
func(buf, size); /* fixed bug */

Rich Jahn
  • 397
  • 3
  • 14
  • 2
    There are many times when you *do* need to use the size of a pointer, e.g. if you're allocating an array of pointers. It would be inappropriate to warn about these, and there's no obvious way for the compiler to know which are which. – Barmar Nov 20 '20 at 19:58
  • I would strongly advise against this sort of macro. You're inventing a new C dialect and it makes it hard for others to maintain the code. Better would be to take a struct which knows its size. – Schwern Nov 20 '20 at 20:10
  • @Barmar Sorry, I didn't mean to imply you never need the sizeof() a pointer. What I'm going for is you cannot use a pointer as an argument in this specific macro, and to say it _must_ be a statically allocated array. – Rich Jahn Nov 20 '20 at 20:10
  • @Schwern Yeah, I can see how a struct would be better, but you would need many different struct types for many different arrays. This macro is used a lot in many different codebases at my company. – Rich Jahn Nov 20 '20 at 20:12
  • If you are using MSVC, then you have the `_countof` macro, which will assert if you give it a pointer argument. Other compilers may have equivalents. See: [Equivalent to MSVC's _count of...](https://stackoverflow.com/q/4415530/10871073). – Adrian Mole Nov 20 '20 at 20:41
  • 1
    Replace the `sizeof` operator with some `SIZEOF` macro and only use it. It can check the size against known pointer size. Can give false positives negatives. Then during the build process `grep` all of the sources and see that `sizeof` is not used. – Eugene Sh. Nov 20 '20 at 20:57
  • @RichJahn Ironically, the type problem can be solved with macros. Look into how GLib does it [for pointer arrays](https://developer.gnome.org/glib/2.66/glib-Pointer-Arrays.html) and [arrays](https://developer.gnome.org/glib/2.66/glib-Arrays.html). It's much safer than passing the array and size separately. – Schwern Nov 20 '20 at 21:30
  • 1
    Please, don't go down this path. It's essential to know what you're working with and to do it right. If you don't know if you can sizeof something, 'cause it may be malloc'd. You're doing something wrong. – stderr Nov 20 '20 at 23:15
  • @AdrianMole Looks like `_countof()` does produce a compile error when desired when compiling as C++, but not with C. MSDN documentation says that as well. – Rich Jahn Nov 21 '20 at 02:09
  • @Schwern In that case you use `g_array_new()` and `g_array_free()`, so it would be dynamic memory allocation. You lose the benefit of automatic memory management with static allocation, where you don't have to have explicit memory management. It's not "bad", but I see it as a tradeoff I guess, and not a silver bullet fix for this. – Rich Jahn Nov 21 '20 at 02:12
  • @RichJahn You don't have to use their library. [Look at how they implement generic types](https://stackoverflow.com/questions/63333480/create-data-type-of-n-size-bytes/63333678#63333678). Adapt that to make your own array structs so you no longer have to pass the size around. – Schwern Nov 21 '20 at 02:16

0 Answers0