Author Topic: New C23 working draft  (Read 12820 times)

0 Members and 1 Guest are viewing this topic.

Offline newbrainTopic starter

  • Super Contributor
  • ***
  • Posts: 1906
  • Country: se
Re: New C23 working draft
« Reply #25 on: June 14, 2022, 01:59:52 pm »
no more forward declaration.
Where do you see that?
In 6.7.2.1 (struct and union) I only see additions related to the attribute specifier sequence, another new thing introduced in C23.

The syntax for struct/union still includes:
Quote
struct-or-union attribute-specifier-sequenceopt identifier
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 190
  • Country: us
Re: New C23 working draft
« Reply #26 on: June 14, 2022, 02:03:12 pm »
Sure does work. I tried it on arm64, amd64, and riscv64 machines.

Sorry, but "I tried it" does not really hold any weight in such matters. It doesn't matter.

The only thing that could make it not work is if rows are padded, in which case m should be rounded up in some way before multiplying. If that happens on some platform you have then 1) that's weird, and 2) that can easily be incorporated with some #if.

An array cannot possibly introduce any padding beyond what is already present inside the individual element. The language guarantees that

Code: [Select]
sizeof(T [N]) == sizeof(T) * N

which immediately implies that

Code: [Select]
sizeof(T [A][B]...[Z]) == sizeof(T) * A * B * ... * Z

That immediately precludes any possibility of "row padding" or anything like that. So, from the pure address arithmetic standpoint your code "should work".

But the language says that your code has undefined behavior. Which means that the compiler can do anything with it. As I said above, the primary source of "undefinedness" in undefined code is the compiler deliberately screwing up your code either to optimize it or to teach you a lesson. The fact that your code "worked" in your experiments simply means that the compiler writers haven't gotten around to it yet.
« Last Edit: June 14, 2022, 03:02:39 pm by TheCalligrapher »
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 190
  • Country: us
Re: New C23 working draft
« Reply #27 on: June 14, 2022, 02:03:47 pm »
no more forward declaration.

What exactly is this about?
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 8349
  • Country: fi
    • My home page and email address
Re: New C23 working draft
« Reply #28 on: June 14, 2022, 03:13:40 pm »
Again, the standard is pretty specific about it: if an array object is declared with a specific size, the language prohibits you from accessing beyond its boundary, i.e. use pointer arithmetic that crosses that boundary. No exceptions are made for sub-arrays within a multi-dimensional array.
Consider the case where you start with a linear (single-dimensional) array, and type-pun that into a multidimensional one.  Where are the boundaries violated?
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 190
  • Country: us
Re: New C23 working draft
« Reply #29 on: June 14, 2022, 04:46:35 pm »
Again, the standard is pretty specific about it: if an array object is declared with a specific size, the language prohibits you from accessing beyond its boundary, i.e. use pointer arithmetic that crosses that boundary. No exceptions are made for sub-arrays within a multi-dimensional array.
Consider the case where you start with a linear (single-dimensional) array, and type-pun that into a multidimensional one.  Where are the boundaries violated?

Type-punning is type-punning. In your example you used type-punning through a union, which is a valid way to type-pun in C. But type-punning is a completely different story. You can basically type-pun anything into anything as long as you stay within the storage and don't run into a trap representation.

Meanwhile, accessing a two-dimensional array `a[N][M]` by pointer arithmetic from `&a[0][0]` with `M * N` range is not a valid way to type-pun a 2D array as a 1D array.
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 190
  • Country: us
Re: New C23 working draft
« Reply #30 on: June 14, 2022, 05:12:52 pm »
1. As K&R declarations/definitions go away, `()` becomes equivalent to `(void)`. No more chastising newbies for `int main()`... End of an era.

2. It is now permissible to omit parameter names in function definitions

Code: [Select]
void foo(int, double) {}
3. I remember someone mentioned that C23 will fix this silly annoyance (and the Wikipedia C23 article mentions it)

Code: [Select]
void foo(const int (*a)[10]) {}

int main()
{
  int a[10];
  foo(&a); /* error: pointers to arrays with different qualifiers are incompatible in ISO C */
}

but the draft document does not seem to mention it in the introductory list of changes.

4. The finally said it explicitly: "The calloc function returns either a pointer to the allocated space or a null pointer if the space cannot be allocated or if the mathematical product nmemb * size is not representable as a value of type size_t."
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17774
  • Country: fr
Re: New C23 working draft
« Reply #31 on: June 14, 2022, 06:16:42 pm »
Whenever I end up using nontrivial 2D arrays (for example linear algebra stuff), I end up having to use origin[row*rowstride + col*colstride] anyway.

Yeah, I personally never *declare* multidimensional arrays in C anyway and never use arrays as function parameters (pointers instead).
The indexing is a trivial task.

I'd be curious to see if using multidimensional arrays might compile to more efficient code than handling the indexing as above, but I suspect this will not make any difference.

And I would have liked C to add an operator to get the number of elements of an array. 50 years of C and will still have to do it with sizeof(A)/sizeof(A[0]) or similar (or define such a macro).
Maybe I missed it though in one of the latest std revisions?
 
The following users thanked this post: Siwastaja

Online magic

  • Super Contributor
  • ***
  • Posts: 8058
  • Country: pl
Re: New C23 working draft
« Reply #32 on: June 14, 2022, 09:27:08 pm »
I'm reading the PDF now, this is going to be the fundamental problem with casting "multidimensional" arrays to ordinary pointers or vice-versa.
Quote
6.2.7

2. All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.

Type compatibility is defined in 6.2.7 and further elaborated on in 6.7.6.2 when it comes to arrays.
Quote
6. For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value.

For int[N][M] and int[N*M] to be compatible, the element types int[M] and int must be compatible, they are not.


This is the usual rule that breaks any type punning by means other than a union (union avoids multiple declarations by being a single declaration of two types simultaneously) or memcpy to a char buffer. It absolutely can be a real world problem, because compilers assume that pointers to different types (other than char) don't overlap in memory and will generate invalid code, such as caching the last value seen through one pointer while the object is being modified through the other pointer.

6.7.6.2 is quite explicit that no exception is being made for re-dimensioning arrays, although sane compilers may make such exception at this time because the construct is somewhat popular. I tried to produce miscompilation with GCC with -fstrict-aliasing and failed so far, but maybe I didn't try hard enough. GCC manual gives some examples of UB code that is likely to fail in practice, but doesn't say anything about arrays.
 
The following users thanked this post: Nominal Animal

Online magic

  • Super Contributor
  • ***
  • Posts: 8058
  • Country: pl
Re: New C23 working draft
« Reply #33 on: June 15, 2022, 08:01:23 am »
By the way, if C had two-dimensional arrays, you could take a pointer to element 0,0 and iterating it till the end of the two dimensional array would not access the array out of bounds. But you can't because of the almost-equivalence of pointers with 1D arrays and lack of true multi-dimensional arrays, with nested arrays being the widely used substitute.

And yes, I'm reading the PDF. They use the d-word when defining arrays. Obviously, it's marketing wank not unlike most of Baterriser claims. No one can be fooled who has ever seen Fortran matrix code and a comparable implementation in C.
 |O
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6403
  • Country: nz
Re: New C23 working draft
« Reply #34 on: June 15, 2022, 10:53:27 am »
Whenever I end up using nontrivial 2D arrays (for example linear algebra stuff), I end up having to use origin[row*rowstride + col*colstride] anyway.

Yeah, I personally never *declare* multidimensional arrays in C anyway and never use arrays as function parameters (pointers instead).
The indexing is a trivial task.

I'd be curious to see if using multidimensional arrays might compile to more efficient code than handling the indexing as above, but I suspect this will not make any difference.

I ran both versions through Clang generating .ll intermediate code, without any middle-end getting called.

The "illegal" version used a multiply and then add and then getelementptr [1] with i8* while the VLA version used getelementptr twice, once for each dimension. That's no real difference in practice.

The bigger difference was that, as the dimension size arguments were declared as "int" on LP64 machines (all three of arm64, amd64, and riscv64), the multiply version used i32 = i32 * i32 while the VLA version immediately cast the dimensions to i64.

So, that's a difference if the array is bigger than 4 GB.

But it's easily fixed with a cast in the array indexing calculation.

[1] for those not familiar with LLVM internals, getelementptr in llvm intermediate code is pretty much exactly an "LEA [base + index*size + offset]" where everything can be variable. A lot of n00bs get confused, thinking it's a memory access. It's not. It's just pure pointer arithmetic.
« Last Edit: June 15, 2022, 11:01:01 am by brucehoult »
 
The following users thanked this post: SiliconWizard

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 8349
  • Country: fi
    • My home page and email address
Re: New C23 working draft
« Reply #35 on: June 15, 2022, 03:17:32 pm »
No one can be fooled who has ever seen Fortran matrix code and a comparable implementation in C.
At the function call ABI level, because of array slicing support, one-dimensional array references tend to be origin,stride,length with each element accessed as (using C syntax) origin[stride*index] for index=1..length, inclusive.  (In fact, gfortran also records offset, minimum_index, and maximum_index also, making it origin[offset+stride*index] for index=minimum_index..maximum_index, or something along those lines.)

Even with this "added complication" in array indexing, naïvely written Fortran array/matrix code tends to beat code written in naïve C to achieve the same, i.e. by physicists and such, in my experience.  It does not mean that "Fortran is faster/better than C", unless you limit the domain to "for naïve programmers".  Since naïvety can be a positive quality for example when making new science utilising linear algebra – such is easier to review, reproduce, and verify –, Fortran will always have niches where it is preferable to C, unless something even more suitable for naïve programmers comes along.

I'm sure most of you have seen my own matrix interface in C, where both matrices and views to matrices are the same thing, so you can have e.g. two matrices and three vectors using the same data – row-major and column-major matrices (transposes), main diagonal and two sub-diagonal vectors (immediately above and below), as often needed for C² continuity in piecewise cubic curve models – where any change to one is immediately visible in all others, because they refer to the exact same data.  I do use row and column numbering starting from zero, though.  In my experience, any heavier operation like matrix-matrix multiplication, benefits from heuristic check that considers the matrix shapes, and reorders one or both matrices to temporary storage to optimize cache locality.  Much better gains are available if sequences of operations (like multiple matrices multiplied together, or raising a square matrix to a power) can be optimized.  Since element access to a matrix just isn't a bottleneck; it's the cache locality/memory bandwidth and algorithmic optimizations (to minimize the number of base operations needed) that yield true efficiency improvements.
 

Online free_electron

  • Super Contributor
  • ***
  • Posts: 9050
  • Country: us
    • SiliconValleyGarage
Re: New C23 working draft
« Reply #36 on: June 15, 2022, 03:29:13 pm »
no more forward declaration.

What exactly is this about?
wishful thinking on my part. i hate the concept of header files. the compilers should collect the function definitions from the source files. you don't need to define a function ahead of time. it is irritating to have to define stuff two times.
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 11157
  • Country: fi
Re: New C23 working draft
« Reply #37 on: June 15, 2022, 05:24:38 pm »
wishful thinking on my part. i hate the concept of header files. the compilers should collect the function definitions from the source files. you don't need to define a function ahead of time. it is irritating to have to define stuff two times.

As much we all hate collecting function prototypes manually to an another file in error-prone manual process (yuk), or automating that with code generation (yuk), this would be too big of a change to be realistic. This is not something you can just remove and replace with something simple; it would require inventing the wheel over again to the point it would be almost like a whole new language, not just improved version of C any more.

One of the key strengths of C is that it does not change too dramatically or fast, but is still maintained.
 

Offline newbrainTopic starter

  • Super Contributor
  • ***
  • Posts: 1906
  • Country: se
Re: New C23 working draft
« Reply #38 on: June 15, 2022, 05:32:41 pm »
wishful thinking on my part. i hate the concept of header files. the compilers should collect the function definitions from the source files. you don't need to define a function ahead of time. it is irritating to have to define stuff two times.
If you want Arduino, you know where to find it :-DD

Such a change is so backwards incompatible to be ever even considered.

Now, that the #include mechanism is not the best possible world and C lacks a proper module concept we can probably agree, but I think you are conflating two issues: the visibility of symbols inside a translation unit, and their accessibility outside, #include has nothing to do with the former.
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline Ed.Kloonk

  • Super Contributor
  • ***
  • Posts: 4000
  • Country: au
  • Cat video aficionado
Re: New C23 working draft
« Reply #39 on: June 15, 2022, 05:33:46 pm »
wishful thinking on my part. i hate the concept of header files. the compilers should collect the function definitions from the source files. you don't need to define a function ahead of time. it is irritating to have to define stuff two times.

As much we all hate collecting function prototypes manually to an another file in error-prone manual process (yuk), or automating that with code generation (yuk), this would be too big of a change to be realistic. This is not something you can just remove and replace with something simple; it would require inventing the wheel over again to the point it would be almost like a whole new language, not just improved version of C any more.

One of the key strengths of C is that it does not change too dramatically or fast, but is still maintained.

Because I'm a dinosaur, I like keeping the func declarations in a list and use the rest of the line to describe more about it's intention (not to be confused with what it actually does).

The other reason is I prefer a basic editor and the handy list helps me pick the right sub with the right spelling.
iratus parum formica
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17774
  • Country: fr
Re: New C23 working draft
« Reply #40 on: June 15, 2022, 07:30:59 pm »
no more forward declaration.

What exactly is this about?
wishful thinking on my part. i hate the concept of header files. the compilers should collect the function definitions from the source files. you don't need to define a function ahead of time. it is irritating to have to define stuff two times.

That's one of the benefits you would get from the implementation of "modules" that I highly suggested earlier.

But note that modules do not necessarily avoid having to define an *interface*, which is what function prototypes roughly provide.
Among languages implementing modules, some require a separate interface, some do not.
Separate interfaces have their benefits too.
 

Online free_electron

  • Super Contributor
  • ***
  • Posts: 9050
  • Country: us
    • SiliconValleyGarage
Re: New C23 working draft
« Reply #41 on: June 16, 2022, 01:10:36 pm »
Such a change is so backwards incompatible to be ever even considered.

how hard is this to implement ? scan all sourcecode to collect function definition. (It's a simple string parser) and write a file that contains all the function prototypes. include that file at the top of the project and start compilation as usual.
you don't have to break anything. simple compiler flag "auto_function_declare = true"

the only thing backwards is C itself ! the compiler is lazy. it needs statement terminators ,  it cant figure out when = means assign and when compare , it needs this, it needs that. many other languages have solved all these irritations long before C even came along.
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline newbrainTopic starter

  • Super Contributor
  • ***
  • Posts: 1906
  • Country: se
Re: New C23 working draft
« Reply #42 on: June 16, 2022, 01:17:35 pm »
it needs statement terminators ,  it cant figure out when = means assign and when compare
:horse:

Quote
how hard is this to implement ?
Without changing rules for linkage of objects (or should they not be included?) and functions, and their visibility?
And what about typedef, that share the name space of ordinary identifiers?
How are conflicts to be resolved?

How hard?
Very hard, I think impossible, keeping some kind of backwards compatibility.
« Last Edit: June 16, 2022, 01:54:24 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 190
  • Country: us
Re: New C23 working draft
« Reply #43 on: June 16, 2022, 06:20:27 pm »
the only thing backwards is C itself ! the compiler is lazy. it needs statement terminators ,

Becuse without them it is impossble to figure out where a statement end.

it cant figure out when = means assign and when compare

Becuse it is impossible to "figure out".

, it needs this, it needs that. many other languages have solved all these irritations long before C even came along.

Becuse those "many other languages" simply don't have the features that lead to those ambuguities.
 
The following users thanked this post: Siwastaja

Online free_electron

  • Super Contributor
  • ***
  • Posts: 9050
  • Country: us
    • SiliconValleyGarage
Re: New C23 working draft
« Reply #44 on: June 16, 2022, 08:43:21 pm »

Becuse those "many other languages" simply don't have the features that lead to those ambuguities.
so remove the source of the ambiguity !
i like how you use amBUGuities... i'm gonna steal that... i came up with one this morning instead of simulator : semi-lie-er

as for the statement end : at the <CR> or<CR><LF>. if the line needs continuation use a continuation character. you need far fewer of those as lines are 80 characters. if the statement doesn't fit in 80 characters : split it. it is too complex to understand anyway.
« Last Edit: June 16, 2022, 08:44:54 pm by free_electron »
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6403
  • Country: nz
Re: New C23 working draft
« Reply #45 on: June 16, 2022, 10:40:29 pm »
the only thing backwards is C itself ! the compiler is lazy. it needs statement terminators ,  it cant figure out when = means assign and when compare , it needs this, it needs that. many other languages have solved all these irritations long before C even came along.

What prevents you from using one of those many other languages?
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17774
  • Country: fr
Re: New C23 working draft
« Reply #46 on: June 17, 2022, 12:52:38 am »
That's getting pretty funny. ;D
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 190
  • Country: us
Re: New C23 working draft
« Reply #47 on: June 17, 2022, 02:17:21 am »

Becuse those "many other languages" simply don't have the features that lead to those ambuguities.
so remove the source of the ambiguity !

"The best cure for dandruff - guillotine"

We should all stick to programming Turing machines. No ambuguities whatsoever.
 
The following users thanked this post: newbrain

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17774
  • Country: fr
Re: New C23 working draft
« Reply #48 on: June 17, 2022, 03:06:25 am »
Ahah. Ambiguity is a relatively subjective notion here anyway when it comes to operators.

In C, there is actually no ambiguity to speak of, since there are two distinct operators for assignment and equality. I would personally call it ambiguous if it had only *one* operator for both operations, which it does not.

Sure you can always prefer other combinations, such as ':=' for assignment and '=' for equality, but that doesn't fundamentally change anything regarding ambiguity. And as others have said, pick another language in this case.

You may also not like the fact that an assignment expression is a value, and maybe that's part of what makes it all feel ambiguous? (Sure this is the reason 'if (a = b)' can lead to programming errors, although those are now caught relatively easily by compilers and should give you a warning.) Well, other languages have that characteristic too.

Or maybe you should have a look at some languages which not only have the '=' and '==' operators, but also '===' and combinations thereof. Does that look even better? :-DD
 

Online magic

  • Super Contributor
  • ***
  • Posts: 8058
  • Country: pl
Re: New C23 working draft
« Reply #49 on: June 17, 2022, 07:27:50 am »
This problem doesn't exist in Microsoft QBasic, Visual BASIC, etc; both operations are = and ambiguity is resolved by assignment not being permitted in expression context and an expression alone (other than function calls) not being a statement.

Not much of value is lost that way, you don't see that sort of C code anyway:
Code: [Select]
foo(a,b) == c+d;
a | c->bar(x);

Only chain assignments are not possible.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf