4 ms·
Tangential, this note from the other answers confuses me as somebody who has no real C experience: > The sizeof way is the right way iff you are dealing with a
by happytoexplain 2y ago
Tangential, this note from the other answers confuses me as somebody who has no real C experience:
> The sizeof way is the right way iff you are dealing with arrays not received as parameters. An array sent as a parameter to a function is treated as a pointer
The conclusion is that it's impossible in that scenario, so you can only manually keep track.
But isn't this what dereferencing is for? What's my fundamental misunderstanding?
- cjensen 2y agoYou're being confused by one of the parts of C that is difficult for beginners to wrap their heads around, and is a trap from the unwary. In C, there are arrays. If you use the identifier that names the array as a parameter to a function, it gets quietly converted to a pointer to the first item of the array and all array size information is lost. So you can obtain the array size, but only if you are dealing with the identifier that directly names the array. If you attempt the same technique on a pointer to the array, bad things will happen.
- LiamPowell 2y ago> If you attempt the same technique on a pointer to the array, bad things will happen. Technically a pointer to the array will work as expected (i.e. void f(int (*x)[5])).
- Marthinwurer 2y agoDereferencing just gets whatever the value is of that data type that is at the memory location in the pointer. That memory location is all the data that is in that pointer, all other data on how to use it is in the compiled-in type. the length isn't stored unless you manually store it.
- kstrauser 2y agosizeof() is evaluated at compile time: https://stackoverflow.com/questions/671790/how-does-sizeof-determine-the-size-of-an-array https://stackoverflow.com/questions/671790/how-does-sizeof-d... If you make an array 6 long, the compiler knows you did that. However, that information isn’t stored in heap anywhere. If all you have is sizeof(somePtr), there’s nothing for it to look at to retrieve the data.
- card_zero 2y agoYeah, it's a pointer which may happen to be a pointer to the start of an array ... or some other element of the array, or a different variable of the same type (the type of the element), or a variable of a different type coerced into being passed as the right type. The compiler doesn't know or care! Do what you like! Hence it can't tell you the size of the thing because the thing could be anything and could have come from anywhere.
- happytoexplain 2y agoWow, that's new to me! Like a macro in languages I'm used to, but smarter. This is key in contextualizing the "it's a pointer" part of the explanation. It sounds like the size of an array is never intrinsic to it, as a data type, regardless of whether what we've got is a pointer. What's important is that sizeof is compile-time, so it can only know the array size in contexts where it can be determined at compile time.
- kstrauser 2y agoYep, that’s correct. The entire data structure of a C array, as available to the running code, is a pointer to the first element. The compiler has that information during compilation but it doesn’t make it trough to the resulting executable.
- o11c 2y agoExcept, not always. For VLAs runtime is involved. This question really needs an answer that's carefully written to handle all 6 cases {C, C++ (since this belongs in a header)} x { normal array, VLA, pointer-which-is-an-error }
- MathMonkeyMan 2y agoIf array is an array of `N` `T`s (`T array[N]`), then `sizeof array` is `N * sizeof(T)`. However, if you have a function parameter spelled `T array[N]`, that's really just a `T *array` with a helpful hint that it probably points to the beginning of an array of `N` `T`s. But it might not... For the case of the function parameter, `sizeof array` is `sizeof(T*)`.
- a2128 2y agoPointers just point to an address in memory. It could point to a single structure or variable, but it also became a standard in C to use pointers to point to the start of an array. When used like this, you have to either agree what the end of an array looks like (e.g. '\00' for end of char array aka string), or manually forward the size of the array to a function, e.g. void do_something(int *numbers, size_t number_count). Accessing elements of the array like numbers[5] is effectively just a nice shorthand for dereferencing (numbers + 5 * sizeof(int)), there is no bounds checking and you can access bad memory with a bad index. Over time people realized this is kinda dumb and annoying, so now C++ has std::span, Rust has slices, which are basically structures that store both a pointer and a size, so you can define functions like void do_something(std::span<int> numbers). C will remain forever though so we have to forever deal with the above
- LiamPowell 2y agoIt was known that this was dumb and annoying around the time C was designed. Ada had the equivalent of std::span as the default for passing arrays in 1982 and I'm sure earlier languages had it before C was even conceived.