3 ms·
The article has examples of array parameters like int b[const 42][24][*] but you can get more fun with variably modified array parameters instead of just
by shift_reset 7y ago
The article has examples of array parameters like
int b[const 42][24][*]
but you can get more fun with variably modified array parameters instead of just constants like 42. For example,
double sum_a_weird_shaped_matrix(int n, double array[n][3*n]) {
double total = 0;
for (int x = 0; x < n; ++x) {
for (int y = 0; y < 3 * n; ++y) {
total += array[x][y];
}
}
return total;
}
has a variable and a more complicated expression in those positions.
But those variably modified parameters can have arbitrary expressions in them, like
int last(size_t len, int array[restrict static (printf("getting the last element of an array of %zu ints\n", len), len--)]) {
return array[len];
}
C++ denies us this particular joy which could have made function overload resolution even more fun.
- multun 7y agoI took the code sample of the article from a snippet intended to be as dirty as possible, and removed most madness out of it. But yeah you're right :D I just wanted to avoid adding one more item in that bullet list.
- stevenhuang 7y agoAnother neat note IIRC is that array parameter sizes don't actually do anything, they just are there for semantic purposes and get treated as raw pointers. So if you do void func(int x[10]); You're free to call it like int k[5]; func(k); And you won't get any warnings. Unsettling!
- shift_reset 7y agoThat's what the static keyword means in those array declarators. void func(int x[static 10]); must be called with an argument that is a pointer to the start of a big enough array of int. I can't get recent GCC or Clang to warn on violations of this, though.
- spc476 7y agoThere are cases where the compiler can't enforce it: void foo(int *p) { func(p); } How can the compiler know if `p` points to space for 10 integers?
- ninkendo 7y agoThe wording in the C FAQ is that arrays “decay” into pointers when you pass them to functions. Which they explain as the reason why you can’t know the size of a passed array (at least in standard C.) The C FAQ is pretty old though, I’ve always wondered how much of that advice changed in C99/C11... from cursory googling things don’t seem to have changed much.
- cryptonector 7y agoIt's funny that K&R chose to have arrays "decay" to pointers, but to allow structs to be passed by value. Thus you can actually pass arrays by value if and only if you wrap them in a struct: struct foo { char a[5]; }; void f(struct foo x) { x.a[4] = '\0'; printf("%s", x.a); } int main(void) { struct foo x; memcpy(x.a, "too big", sizeof(x.a)); f(x) printf("%s", x.a); /* read past end of x, crash */ return 0; } I'm thankful they didn't make structs decay into pointers!
- jandrese 7y agoI figured that having arrays decay into pointers is one of those features that got grandfathered in because changing it would have broken the dozen or C programs that existed at the time. It's a real shame too because a working sizeof() for strings could have avoided a LOT of C exploits over the years.