3

I'd like to replace the following macro with an actual function in C.

#define ARRAY_LENGTH(a) (sizeof(a)/sizeof((a)[0]))
krithik
  • 27
  • 3
  • 10
    Can't be done. When the array is passed to a function, the size information is lost. See [this post](https://stackoverflow.com/questions/1461432/what-is-array-decaying) for more information. – user3386109 Mar 28 '16 at 22:42
  • 2
    Why do you want this? There are good applications for macros. This is one of them. – too honest for this site Mar 28 '16 at 22:43
  • @user3386109: More exactly: the array decays to a pointer to its elements, which is apparently a different type. But even if it would not, You cannot pass an arbitrary type to a function while preserving type information. – too honest for this site Mar 28 '16 at 22:44
  • I had a feeling the use of the macro would be unavoidable. I guess I would've liked to know if an alternative existed. But in any case certainly good to learn about array-decay. – krithik Mar 29 '16 at 00:18
  • 2
    @Olaf I wouldn't say that's exact, either; "the array decays" implies that a permanent side-effect occurs upon the array. What happens when the function returns? Does the array *un-decay*? I know that you know of the terminology used by the standard... Perhaps you could kill two birds in one stone and explain how functions receive objects with copied values, and during that copy there's a *conversion*. In any case, the term *decays* is no less confusing than using the term the standard uses; in fact it can be more confusing. Please stop that... – autistic Mar 29 '16 at 03:02

3 Answers3

1

Keep your macro. Replacing it is a mistake. When you pass an array to a function it decays into a pointer and you lose size information.

T Johnson
  • 824
  • 1
  • 5
  • 10
  • Please see [my criticism regarding the implications of phrases like "it (sic: the array) decays"](http://stackoverflow.com/questions/36272402/length-of-arbitrary-array-type-in-c-function#comment60176087_36272402), above... – autistic Mar 29 '16 at 03:08
1

As others have said, you can't.


When you pass an argument to a function, the value of that expression is copied into a new object.

One problem is functions can't have arrays as arguments. Array declarations in function prototypes are converted to pointer declarations.

Similarly, the expression denoting the array that you're passing will be converted to a pointer to the first element of the array.

Another problem standing in your way is that C has no generic functions. There is no way to provide a function with an "array of T", where T can be any type you like, aside from using a void * parameter and passing size information separately.


Function-like macros as expanded at a different stage, however. They're translated during compilation; imagine copying and pasting the code for the macro everywhere it's mentioned, substituting the arguments, prior to compilation. That's what your compiler does with macros.

For example, when you write printf("%zu\n", ARRAY_LENGTH(foo)); it replaces this with: printf("%zu\n", (sizeof(foo)/sizeof((foo)[0])));.


P.S. sizeof is not a function; it's an operator... Coincidentally, it is one of the few (the others being the &address-of operator and the newly adopted _AlignOf operator) which don't cause the array expression to be converted to a pointer expression.

Community
  • 1
  • 1
autistic
  • 1
  • 3
  • 35
  • 80
-5
int arraySz(void **a)
{ 
return(sizeof(a[])/sizeof(a[][]));
}

However a would have to be pointing to an existing rectangular array, not just be a pointer to a pointer, or return value from malloc().

Arif Burhan
  • 507
  • 4
  • 12
  • For a starter: `a` is not an array, thus where is the size? Note: you cannot pass an array to a function. And your code looses vital type information of the elements. There are other problems&faults in that code. More than it has lines. – too honest for this site Mar 28 '16 at 22:48