5 ms·
Yes, needing a fixed-sized array seems like a fairly common need to me. a := [5]int32{0, 1, 2, 3, 4} // Go let mut array: [i32; 5] = [0, 1, 2, 3, 4];
by Xeoncross 4y ago
Yes, needing a fixed-sized array seems like a fairly common need to me.
a := [5]int32{0, 1, 2, 3, 4} // Go
let mut array: [i32; 5] = [0, 1, 2, 3, 4]; // Rust
- masklinn 4y agoC has fixed-size arrays. The problem is that it doesn't use them much, and gets rid of them as soon as possible: int a[5] = {1, 2, 3, 4, 5, 6}; printf("%d\n", a[8]); in clang, this warns, by default, on both misuse sites "excess elements in array initializer" and "array index is past the end of the array". Which is good. However things go downhill as soon as you pass the arrays downstack: #include <stdio.h> static void foo(int *a) { printf("%d\n", a[8]); } static void bar(int a[]){ printf("%d\n", a[8]); } static void qux(int a[6]){ printf("%d\n", a[8]); } int main() { int a[5] = {1, 2, 3, 4, 5}; foo(a); bar(a); qux(a); } no warning anywhere, even under "-Wall -Weverything".
- klodolph 4y agoYeah, so the syntax is a bit funny but you can actually get the bounds checking you want here: #include <stdio.h> static void qux(int a[static 6]){ printf("%d\n", a[8]); } int main() { int a[5] = {1, 2, 3, 4, 5}; qux(a); } I get, test.c:9:5: warning: array argument is too small; contains 5 elements, callee requires at least 6 [-Warray-bounds] I did not enable any warning flags at all, this is just default Clang on a Mac. If you want to catch the a[8] inside the function you need something else.
- Jasper_ 4y agoUnfortunately, `int a[static 3][static 4]` does not work.
- klodolph 4y agoThat’s because you’d write it as: int a[static 3][4] You only need to put static on the outermost type, the one that decays into a pointer. Same thing applies if you need restrict: int a[static restrict 3][4] which is ugly but gets the job done. Think of int a[3][4], when used as a function parameter, as “pointer to int[4]” (the 3 disappears completely), and think of int a[static 3][4] as “pointer to first of at least 3 int[4]”. (Not trying to defend C here, just explaining how C works.)
- WalterBright 4y agoThe explicit "6" is a problem if you aren't using fixed size arrays.
- klodolph 4y agoYes, this was in direct response to someone talking about fixed-size arrays. Think of this as just “one small way in which C does not happen to be broken” rather than some kind of endorsement of C! Note that you could static void qux(int n, int a[n]) but this changes the interface somewhat and there are lots of reasons why you might want to avoid VLAs in C.
- WalterBright 4y agoThe problem with that syntax is you have to repeat it every time `a` is forwarded to another function. The array data and length need to be combined into a single semantic entity.
- klodolph 4y agoYes, but I don't think a deeper discussion about the flaws of array handling C is really going to illuminate anything here. The conclusions generally go in one of three ways--either you choose to use a different language, choose to deal with C (with tools like static analyzers or instrumentation), or choose to make proposals to the C committee. Proper array types are not present in C and they're unlikely to be added at any point in the future, so if the conversation is "the array data and length need to be combined into a single semantic entity", then the conversation is no longer about C, but the starting point for choosing another language. The int a[static 6] syntax made it into the language because it's a small enough change that it's not disruptive to existing uses of C, but it still has some benefit (I've used it, I've seen its benefits).
- WalterBright 4y agoMy proposal is backwards compatible and will not disrupt existing use.
- ryao 4y agoIt appears that Clang will warn even without this syntax while GCC does not warn unless it has this syntax. At least, it did when I dropped the `static 6` from the example.
- abcd_f 4y ago> Yeah, so the syntax is a bit funny That's a mild understatement.
- deleted 4y ago[deleted]
- int_19h 4y agoTo pass fixed-size arrays in a way that preserves the type and allows checking their bounds, you can use pointers-to-arrays: static void foo(int (*a)[6]) { printf("%d\n", (*a)[8]); // warning: array index 8 is past the end of the array (which contains 6 elements) } int main() { int a[5] = {1, 2, 3, 4, 5}; foo(&a); // warning: incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[6]' } This is all vanilla C89, so it works even with very old compilers, so long as they're conformant.