4 ms·
Because that's how the machine sees C arrays. It would take an extra (invisible) parameter on the stack to implicitly pass the array size into the function, a
by syncsynchalt 11y ago
Because that's how the machine sees C arrays. It would take an extra (invisible) parameter on the stack to implicitly pass the array size into the function, a thing which is very much against the spirit of C.
The only real surprises/magic in C are things like:
- addition/subtraction on typed pointers has an implicit multiply by sizeof(type)
- type conversion between floats and ints
- acconsta 11y agoBut the size of C89 arrays is fixed and known at compile time. Why would the length need to be passed?
- klodolph 11y agoIt's not necessarily known by the caller, since the array might be declared with an unspecified size and defined in a different translation unit.
- acconsta 11y ago"might" is the key word there though. What if the array has a statically known size, like the code sample in the email? I suppose it could just be for consistency.
- maximilianburke 11y ago> Because that's how the machine sees C arrays. It would take an extra (invisible) parameter on the stack to implicitly pass the array size into the function, a thing which is very much against the spirit of C. It would only require a separate parameter if you needed to pass arbitrary-sized arrays. In this example, if the prototype contains the array size: int foo(char array[30]); It would not be difficult for the compiler to only allow arrays of that length to be passed as parameters, and no invisible parameters are necessary, assuming also that the function implementation made the same assumption of array length. Developers who handle arrays of arbitrary length tend to already encode a length parameter, it's this case where it looks to the developer like they are encoding a length value that is the deceptive/problematic case.
- geocar 11y ago> It would not be difficult for the compiler to only allow arrays of that length to be passed as parameters It would be extremely difficult for the compiler, without changes to the C spec and most ABIs, to simultaneously provide that protection for heap-allocated objects, for example: foo(malloc(30)); > Developers who handle arrays of arbitrary length tend to already encode a length parameter, it's this case where it looks to the developer like they are encoding a length value that is the deceptive/problematic case. The most common arrays of arbitrary length in C programs are almost certainly C "strings" which are usually 0-terminated instead of including a length value.
- mortehu 11y agoThis is one of the many uses of the static keyword in C99: void ten(char foo[static 10]) { } void generates_warning() { char foo[3]; ten(foo); } This causes clang to emit the following warning: > warning: array argument is too small; contains 3 elements, callee requires at least 10
- merlincorey 11y agoThe warning is true - it is "at least" 10: char ten(char foo[static 10]); char ten(char foo[static 10]) { return foo[1]; } void generates_no_warning(void); void generates_no_warning() { char foo[30]; ten(foo); } int main() { generates_no_warning(); } Modified also so it would build cleanly with -Weverything -Werror
- uxcn 11y agoIt avoids stepping on memory elsewhere in the program though. My personal preference for C99 and above is to pass the length as a parameter. int do_stuff(size_t len, int64_t arr[len]); It still suffers from the pointer decay problem, but it at least forces whoever is reading/writing the code to acknowledge the length.
- uxcn 11y agoHow does that parse? I thought static was only a storage class.
- Athas 11y ago> Because that's how the machine sees C arrays. It would take an extra (invisible) parameter on the stack to implicitly pass the array size into the function, a thing which is very much against the spirit of C. In this case, the size is specified as a compile-time constant, however, which seems like it could work. All it would do is change the semantics of sizeof(), really. Also, I am doubtful whether it would really be a problem to have "invisible" parameters. C doesn't even specify a stack as I remember it, and compilers are certainly free to pass as many function parameters in registers as they are able to.
- geocar 11y agoIt is an ABI change.
- syncsynchalt 11y agoTrue, someone else pointed out that this could all be done as compile time checks, which would have no runtime/ABI impact. There are interesting stories from the early days of C when it was first codified that say a lot about the whys and hows of the language that we have today. In particular I'm thinking of the fact that the compiler and what we now think of "compiler warnings" came from two different warnings (cc vs lint). This is because the C compiler was the largest C program and generally took every bit of memory available to do it, there was no room for any kind of sanity checking on that code. I've heard it said that to include a new feature "n" in the language, they generally had to rework at least some of the existing compiler code with feature "n-1" to simplify/shrink it enough to fit the new feature. In that kind of environment you get a language with very little input checking, beyond the rules of the grammar itself (which was as small as possible).