1

As I understand it every VLA have an hidden variable of it's size which value can be 'acquired' by sizeof operator. What I don't get here is pointer to VLA's used in function parameters - why isn't their size automatically deduced and stored in this hidden variable - why we should explicitly provide it. And in this case why should we even use it given that we have already the type 'pointer to array of unknown size'?

What I mean is this:

void func(size_t, int (*)[*]); //function accepting pointer to VLA

void func_1(size_t, int (*)[]); //function accepting pointer to array of unknown bound

void func(size_t sz, int (*parr)[sz]) //implementation of 'func'
{
    printf("%lu", sizeof(*parr) / sizeof(int));

    printf("%lu", sz);
}

void func_1(size_t sz, int(*parr)[]) //implementation of 'func_1'
{
    //printf("%lu", sizeof(*parr) / sizeof(int)); //error: invalid application of 'sizeof' to an incomplete type 'int []'

    printf("%lu", sz);
}

As I can see it the only benefit of using 'func' instead of 'func_1' is that 'sizeof' operator will return a copy of the initial value of 'sz'.

Example usages of the above functions:

int main()
{
    size_t sz = 3;

    int arr[sz];

    func(sizeof(arr) / sizeof(int), &arr);

    func_1(sizeof(arr) / sizeof(int), &arr);

    return 0;
}

Why can't the size of pointer to VLA parameter be assigned implicitly? This would at least make some good use of the syntax:

void func(int (*parr)[*]) // size copied from function argument
{
    printf("%lu", sizeof(*parr) / sizeof(int));

    printf("%lu", sz);
}

And then calling the function like this:

int main()
{
    size_t sz = 3;

    int arr[sz];

    func(&arr);

    return 0;
}

Will cause array hidden size variable with value of '3' to be passed as hidden argument to 'func' creating code similar to instancing previous 'func' with current syntax and using 'sizeof' operator to passed array.

If you're curios enough compiling the proposed syntax into whatever Clang compiler - you'll get an easter egg (;.

AnArrayOfFunctions
  • 3,452
  • 2
  • 29
  • 66
  • 1
    There isn't any "hidden variable". `sizeof` is figured at compile time. See http://stackoverflow.com/questions/2615203/is-sizeof-in-c-evaluated-at-compilation-time-or-run-time – Weather Vane Apr 07 '15 at 21:40
  • Sorry but this case is different. This is not an ordinary type but a VA one. – AnArrayOfFunctions Apr 07 '15 at 21:41
  • I'll say it again after your edit. Calling `func(&arr);` will know nothing about how many array elements there are, or even whether it is an array or a single value. there is NO hidden size, it's just a pointer. – Weather Vane Apr 07 '15 at 21:50
  • But 'sizeof(arr)' does. And mostly implementing it is done via hidden variable in the case of 'VA'. I smell you don't know what a type system is. – AnArrayOfFunctions Apr 07 '15 at 21:51
  • I would stop commenting right now with the hope of meeting some better educated C programmer (which had read the ISO standard - best). – AnArrayOfFunctions Apr 07 '15 at 21:54
  • This is a C tag, you just edited out your C++ comment. The function `main()` that declares the array knows its size. The function `func()` that receives its pointer, does not. – Weather Vane Apr 07 '15 at 21:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/74665/discussion-between-fisocpp-and-weather-vane). – AnArrayOfFunctions Apr 07 '15 at 22:00
  • Stop calling us nerds and please read the answers. – Weather Vane Apr 07 '15 at 22:02
  • Re your recent edit "we have already the type 'pointer to array of unknown size'?" You have it in a nutshell. It's a pointer to unknown size, and there is no hidden size, it is unknown. – Weather Vane Apr 07 '15 at 22:07
  • Please stop spamming on this question. Continue here - http://chat.stackoverflow.com/rooms/74665/discussion-between-fisocpp-and-weather-vane – AnArrayOfFunctions Apr 07 '15 at 22:09
  • Use `%zu`, not `%lu`, to print values of type `size_t`. – Keith Thompson Apr 07 '15 at 22:49

3 Answers3

2

The size of a variable-length array (VLA) is associated with the type, not with an object.

For example, given:

size_t n = 41;
int vla[n+1];
printf("sizeof vla = %zu\n", sizeof vla);

the compiler creates an anonymous object initialized to n+1, which I'll call _anon, and defines a type int[_anon], which is the type of the array object vla. (Note that changing the value of n later does not change the value of _anon or the size of the VLA type).

You could also write:

size_t n = 41;
typedef int vla_t[n+1];
vla_t vla;

Applying sizeof to an expression (which, in this case, happens to be an object name) yields the size of that expression's type.

Inside func, the type of vla is not visible, so there's no way to get its size. parr is a pointer to an array of int of unspecified size. The types int[] (an array of unspecified size) and int[n+1] (a variable-length array of length n+1)` are compatible, but not the same type.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
1

The length of a variable-length array is only known locally (as it must be, in order to stack-allocate the storage and to provide sizeof semantics). When it's passed to a function, it's just a regular array type, so the size has to be explicitly passed.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
  • Then what's the propose of VLA parameter types. As they are now - I don't see any good usage of them. – AnArrayOfFunctions Apr 07 '15 at 21:43
  • 1
    It's pretty limited... it allows a function declaration to be coy about the length of its VLA type, while allowing the definition to specify it based on actual parameters. It doesn't itself cause the size to be passed. – Sneftel Apr 07 '15 at 21:52
  • So basically it only allows an implicit copy of some value which can be later received by sizeof operator. This is how I see it. – AnArrayOfFunctions Apr 07 '15 at 21:58
  • Yep. My read is, the design of the feature was intended to avoid complicating the ABI in any way. From the point of view of calling conventions, VLA parameters are non-entities. The only required support is in the code generation for the function itself. – Sneftel Apr 07 '15 at 22:16
  • @Sneftel I don't quite understand what do you mean? And more importantly why would we ever use pointer to VLA instead of pointer to array of unknown size? – AnArrayOfFunctions Apr 07 '15 at 22:20
  • Actually, looking back, Weather Vane is right -- the called function can't use `sizeof` to reconstruct the VLA length. So the only additional functionality comes into play in the case of multidimensional arrays. – Sneftel Apr 07 '15 at 22:25
  • For examples of the use of VLAs in multidimensional arrays, see http://stackoverflow.com/questions/17371645/parameter-of-a-function . But again, the `[*]` is not necessary -- it's just to mark the array as a VLA, without the need to name its dimensions. – Sneftel Apr 07 '15 at 22:27
  • Unless you use a pointer to VLA as in my case. But you didn't answer my previous questions. I mean there is already such thing and it's called array of unknown bound(with the small exception of 'sizeof' as noted). – AnArrayOfFunctions Apr 07 '15 at 22:27
0

In a nasty horrible kludge which should have been abolished decades ago, but is relied upon by too much code to be done away with now, C compilers regarded all function parameters of array types as being equivalent to parameters of pointers-to-element type, whether the array size was specified or not.

There would probably not be any major technical difficulties with defining a syntax by which a function could be passed arrays of arbitrary size and automatically know how big they are. Unfortunately:

  1. Passing arrays to functions presently means passing a pointer to the first element; adding a new syntax where it means something else would create more confusion than it resolves.

  2. If existing code receives a pointer and an integer, and regards that pointer as identifying the first element of an array of a specified length, passing that "array" to a method which expects a "new-style" array could be tricky.

The second problem might be overcome by adding a syntax to turn a pointer/length combo into an "known-size array" that could be passed to methods that accept such things. The former problem, however, will probably be unsolvable unless or until C is replaced with a language which isn't focused on pointer "optimizations" which aren't even relevant anymore.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • @FISOCPP: A parameter of type `int*[]` is equivalent to one of type `int**`; adding a parenthesis around the `*` doesn't change that. While it's possible to declare VLA variables, and would in theory be possible to declare VLA parameters, there's no such thing as a VLA type, nor a pointer to a VLA (as distinct from a pointer to its first element). – supercat Apr 07 '15 at 21:53
  • Nope it is. Come on - ISO nerds - where are you? – AnArrayOfFunctions Apr 07 '15 at 21:57
  • Given `int n = 42;`, `int[n]` is a VLA type, and `int (*)[n]` is a pointer-to-VLA type, just like `int (*)[42]` is a pointer-to-array type. The problem (well, one problem) is that VLAs can only be defined at block or prototype scope; you can't define a VLA object and pass its address to a function that knows about its type. – Keith Thompson Apr 08 '15 at 01:02
  • @KeithThompson: Man those pointers are confusing (I reaffirm my statement about kludginess); I miss Turbo Pascal: `^Array of Integer` versus `Array of ^Integer`. In any case, can you cite a current definition of "type"; I'd be curious to see how it's changed. I'm also curious how all this stuff interacts with typedefs and parameter passing, and what fraction of C programmers really understand all of the rules. I've been a C programmer for 25+ years and I still keep finding weird things I never knew. – supercat Apr 08 '15 at 15:38
  • @supercat: [N1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) is the latest public draft of the C standard; section 6.2.5 covers types. The [comp.lang.c FAQ](http://www.c-faq.com/) is also an excellent resource. – Keith Thompson Apr 08 '15 at 15:42
  • @KeithThompson: I didn't see a clear description in that section of the role that parentheses play, nor how typedefs interact with everything else. – supercat Apr 08 '15 at 18:31