News for hackers. Stuff that matters.
Re:Checked C by klodolph on Wednesday December 21, 2022 @03:58PM (#34086304)
Yeah, 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.

Re:Checked C by WalterBright on Wednesday December 21, 2022 @04:01PM (#34086344)
The explicit "6" is a problem if you aren't using fixed size arrays.
Re:Checked C by klodolph on Wednesday December 21, 2022 @04:10PM (#34086436)
Yes, 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.
Re:Checked C by WalterBright on Wednesday December 21, 2022 @05:06PM (#34087007)
The 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.
Re:Checked C by klodolph on Wednesday December 21, 2022 @05:28PM (#34087254)
Yes, 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).

Re:Checked C by WalterBright on Wednesday December 21, 2022 @05:51PM (#34087437)
My proposal is backwards compatible and will not disrupt existing use.
Re:Checked C by klodolph on Wednesday December 21, 2022 @05:59PM (#34087527)
Do you have a more complete write-up somewhere? At face value, it looks like something that wouldn’t make it into the C standard, because VLAs were too much for the standard to bear. It’s also unclear how multidimensional arrays would work—presumably, you would want that to be possible, and distinct from fat-pointer-to-fat-pointer-array.
Re:Checked C by WalterBright on Wednesday December 21, 2022 @06:14PM (#34087644)
No, that's all I got, although since it is lifted directly from D, you can get a complete treatment there.

VLAs had a poor cost/benefit because they're just too awkward to use. 20 years experience with D shows that the [] syntax knocks it out of the park.

Any combination of static/fat arrays can be made for multidimensionality. For example,

    [..][3]   array of 3 fat pointers
    [3][..]   fat pointer to 3 element array
    [3][3]    array of 3 3-element arrays
    [..][..]  fat pointer to array of 3 fat pointers
etc.
Re:Checked C by klodolph on Wednesday December 21, 2022 @06:21PM (#34087711)
I guess what I would want is to be able to have a fat pointer to a multidimensional array, like I can do in Fortran, NumPy, etc. Why is the 1D case special, here?

My other questions are how do you create one of these fat pointers, how do you get the length, etc. This sounds to me like VLAs, but with a bigger change to the language, but unable to handle multidimensional arrays. VLAs, for all their faults, at least fit into the language for users well enough that people accidentally use them all the time (not necessarily a good thing).

Re:Checked C by WalterBright on Wednesday December 21, 2022 @07:42PM (#34088298)
> a fat pointer to a multidimensional array

    T[3][4][..] a;
> length

    a.length
Re:Checked C by thayne on Thursday December 22, 2022 @12:46AM (#34090244)
I really want C to have a slice/fat-pointer-array type, because C is the least common denominator for ABIs and any kind of FFI, and since it doesn't have something like that, it complicates FFI from languages that have a more sane way of handling arrays.

I'd even be happy if the standard just included a macro like:

#define ARRAY(T) struct { T *ptr, size_t len }

Along with a few functions for working with such types.

Although that would be kind of unwieldy to use in C, since you would need a typedef to actually use any specific types.

Re:Checked C by uecker on Friday December 23, 2022 @05:53PM (#34111524)
I am relatively sure we will end up adding a fat pointer next round.

So long, you can look at my experiments using a struct type here: https://github.com/uecker/noplate/

The typedef thing will go away with C2X where you do this in place.

Re:Checked C by LegionMammal978 on Wednesday December 21, 2022 @08:15PM (#34088519)
That does not change the interface of the function. Function type compatibility looks at the adjusted parameter types, so the parameter is always treated as a simple pointer. Therefore, all of these declarations could be used to refer to the function:

  static void qux(int n, int *a);
  static void qux(int n, int a[]);
  static void qux(int n, int a[*]);
  static void qux(int n, int a[n]);
  static void qux(int n, int a[12345]);
Weird interface problems mainly come when you have VLA types behind pointers.
Re:Checked C by Jasper_ on Wednesday December 21, 2022 @04:00PM (#34086325)
Unfortunately, `int a[static 3][static 4]` does not work.
Re:Checked C by klodolph on Wednesday December 21, 2022 @04:12PM (#34086459)
That’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.)

Re:Checked C by ryao on Wednesday December 21, 2022 @05:28PM (#34087249)
It 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.
Re:Checked C by abcd_f on Thursday December 22, 2022 @02:50AM (#34090901)
> Yeah, so the syntax is a bit funny

That's a mild understatement.