How do I check the length of subarray (*last) in this example?
int
main()
{
int *arr[3];
arr[0] = (int[]){1, 2, 9, 4, 5};
arr[1] = (int[]){10, 2, 8};
arr[2] = (int[]){20, 2, 7, 0, 10};
int *last = arr[2];
return 0;
}
without using sizeof(because of pointer) and without
while (*last) { ... }
because of zero in array?
CodePudding user response:
If you have an array whose length can only be known at run-time, you have to somehow store enough information to recover that length. That might be by simply storing the length, either as part of the array or in some parallel structure, or putting a sentinel value at the end of the array (if there is a possible sentinel value which will never appear as actual data), or in some other way, depending on your creativity.
If the lengths can be computed at compile-time, you could use some kind of macro hack to store the lengths in your data. But you need to be aware of the lifetime of a Compound Literal:
- The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.
So it's safe to store a pointer to a compound literal declared at the top level, and mostly safe (but not necessarily good style, see Note 1) to store a pointer to a compound literal declared in the outer block of main()
, which won't be exited until the program terminates. But if you store the address of a compound literal declared anywhere else in the program, you need to make sure that the object in which you store the pointer will not outlive the compound object. In particular, returning the address of a compound literal from a function is a recipe for disaster.
So in the particular case of your example, you could use the following "X-macro" hack (but it's really not advisable):
int main(void) {
#define ARR \
X(1, 2, 9, 4, 5), \
X(10, 2, 8), \
X(20, 2, 7, 0, 10)
#define X(...) (int[]){__VA_ARGS__}
int *arr[] = { ARR };
#undef X
#define X(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
int arr_len[] = { ARR };
#undef X
#undef ARR
printf("The last element of arr[2] is %d\n", arr[2][arr_len[2] - 1]);
}
Notes
- Storing the pointer to a compound literal declared in the outer block of
main()
is bad style because the assignment might later be moved into a sub-block or different function, creating a dangling pointer.