• "span"

    From Stefan Ram@3:633/280.2 to All on Fri Mar 22 22:30:56 2024
    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls
    "f( a )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then
    knows the length of "a". This is supposed to be less error prone
    than passing a pointer with a separate length argument.

    Of course, I immediately wondered whether one could implement
    such a "span" for C, and here's a draft:

    #include <stdio.h>

    #define SPAN_PARAM(x,a,n) x*a,size_t const n
    #define SPAN(a) a,(sizeof a/sizeof 0[a])

    void print( SPAN_PARAM( int, a, n ))
    { for( size_t i = 0; i < n; ++i )
    printf( "%lld: %d\n", i, a[ i ]); }

    int main( void )
    { int a[ 3 ]={ 4, 6, 8 };
    print( SPAN(a) ); }

    . But since C is another language, there are other forces at work,
    which means that the overall usability of such macros in C might not
    make their definition and use worthwhile. Of course, the "smart" span
    type in C++ surely can do more than my simple macros can do in C!

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: Stefan Ram (3:633/280.2@fidonet)
  • From Thiago Adams@3:633/280.2 to All on Fri Mar 22 22:51:18 2024
    On 22/03/2024 08:30, Stefan Ram wrote:
    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls
    "f( a )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then
    knows the length of "a". This is supposed to be less error prone
    than passing a pointer with a separate length argument.

    Of course, I immediately wondered whether one could implement
    such a "span" for C, and here's a draft:

    #include <stdio.h>

    #define SPAN_PARAM(x,a,n) x*a,size_t const n
    #define SPAN(a) a,(sizeof a/sizeof 0[a])

    void print( SPAN_PARAM( int, a, n ))
    { for( size_t i = 0; i < n; ++i )
    printf( "%lld: %d\n", i, a[ i ]); }

    int main( void )
    { int a[ 3 ]={ 4, 6, 8 };
    print( SPAN(a) ); }

    . But since C is another language, there are other forces at work,
    which means that the overall usability of such macros in C might not
    make their definition and use worthwhile. Of course, the "smart" span
    type in C++ surely can do more than my simple macros can do in C!


    (
    C++ proposals use new type<T> instead of qualifiers. This creates a big
    mess on the type system and incompatibility with C.
    I don't have idea how/why they do this constantly.
    )

    C does not need this for parameters since the current array syntax
    already cover that.

    void f(int n, int a[n])

    The problem is the syntax for pointers, this may be necessary in other contexts other than in parameters.


    C already have a syntax for pointer to array

    int (*)[2] p;

    The problem of this syntax is C code normally use pointer directly
    and a pointer to array requires *p everywhere. Having an specific syntax
    for pointer length makes the code transition from non-annotated to
    annotated much easier. It also avoid lots of (*p)[index] and have just p[index].


    Does anyone have a suggestion for syntax to give pointers the length information?

    One try is

    int *[2] p;

    but the problem of this syntax is it is ambiguous with (cast)

    (int *[2]) //pointer to 2 ints, or pointer to array of 2 ints

    This alternative

    (int [2]*)
    is harder to parse since first it thinks it is array then it need fo
    "fix" to be a pointer.













    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Ben Bacarisse@3:633/280.2 to All on Sat Mar 23 11:17:11 2024
    ram@zedat.fu-berlin.de (Stefan Ram) writes:

    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls
    "f( a )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then
    knows the length of "a". This is supposed to be less error prone
    than passing a pointer with a separate length argument.

    Of course, I immediately wondered whether one could implement
    such a "span" for C, and here's a draft:

    #include <stdio.h>

    #define SPAN_PARAM(x,a,n) x*a,size_t const n
    #define SPAN(a) a,(sizeof a/sizeof 0[a])

    The usual reason given for writing 0[a] in a macro is so that
    parentheses are not needed as they would be (recommended) for *(a) or
    (a)[0]. But since you don't seem to care about writing a rather than
    (a) I don't see why you wrote 0[a] rather than either *a or a[0].

    void print( SPAN_PARAM( int, a, n ))
    { for( size_t i = 0; i < n; ++i )
    printf( "%lld: %d\n", i, a[ i ]); }

    What happens when print wants to pass 'a' to another function that takes
    a span?

    int main( void )
    { int a[ 3 ]={ 4, 6, 8 };
    print( SPAN(a) ); }

    --
    Ben.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Ben Bacarisse@3:633/280.2 to All on Sat Mar 23 11:19:02 2024
    Thiago Adams <thiago.adams@gmail.com> writes:

    On 22/03/2024 08:30, Stefan Ram wrote:
    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls
    "f( a )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then
    knows the length of "a". This is supposed to be less error prone
    than passing a pointer with a separate length argument.
    Of course, I immediately wondered whether one could implement
    such a "span" for C, and here's a draft:
    #include <stdio.h>
    #define SPAN_PARAM(x,a,n) x*a,size_t const n
    #define SPAN(a) a,(sizeof a/sizeof 0[a])
    void print( SPAN_PARAM( int, a, n ))
    { for( size_t i = 0; i < n; ++i )
    printf( "%lld: %d\n", i, a[ i ]); }
    int main( void )
    { int a[ 3 ]={ 4, 6, 8 };
    print( SPAN(a) ); }
    . But since C is another language, there are other forces at work,
    which means that the overall usability of such macros in C might not
    make their definition and use worthwhile. Of course, the "smart" span
    type in C++ surely can do more than my simple macros can do in C!


    (
    C++ proposals use new type<T> instead of qualifiers. This creates a big
    mess on the type system and incompatibility with C.
    I don't have idea how/why they do this constantly.
    )

    C does not need this for parameters since the current array syntax already cover that.

    void f(int n, int a[n])

    Although you can't rely on this anymore since it's now an optional part
    of the language.

    ....
    C already have a syntax for pointer to array

    int (*)[2] p;

    I think you mean

    int (*p)[2];

    --
    Ben.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Kaz Kylheku@3:633/280.2 to All on Sat Mar 23 12:11:28 2024
    On 2024-03-23, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
    ram@zedat.fu-berlin.de (Stefan Ram) writes:

    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls
    "f( a )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then
    knows the length of "a". This is supposed to be less error prone
    than passing a pointer with a separate length argument.

    Of course, I immediately wondered whether one could implement
    such a "span" for C, and here's a draft:

    #include <stdio.h>

    #define SPAN_PARAM(x,a,n) x*a,size_t const n
    #define SPAN(a) a,(sizeof a/sizeof 0[a])

    The usual reason given for writing 0[a] in a macro is so that
    parentheses are not needed as they would be (recommended) for *(a) or
    (a)[0]. But since you don't seem to care about writing a rather than
    (a) I don't see why you wrote 0[a] rather than either *a or a[0].

    void print( SPAN_PARAM( int, a, n ))
    { for( size_t i = 0; i < n; ++i )
    printf( "%lld: %d\n", i, a[ i ]); }

    What happens when print wants to pass 'a' to another function that takes
    a span?

    How about linking the names of a and the size, like a and a_n?
    Then we can make sure there is a _n size, whether we have an
    array or pointer:

    #include <stddef.h>
    #include <stdio.h>

    #define SPAN_DEF(type, a, size, init) \
    type a[size] = init; const size_t a ## _n = size

    #define SPAN_PARAM(type, a) \
    type *a, size_t const a ## _n

    #define SPAN(a) a, a ## _n

    void print(SPAN_PARAM(int, a))
    {
    for (size_t i = 0; i < a_n; i++)
    printf("%zd, %d\n", i, a[i]);
    }

    void print_wrap(SPAN_PARAM(int, a))
    {
    print(SPAN(a));
    }

    int main(void)
    {
    SPAN_DEF(int, a, 42, { 0 });
    print_wrap(SPAN(a));
    }

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Thiago Adams@3:633/280.2 to All on Sun Mar 24 01:16:08 2024
    Em 3/22/2024 9:19 PM, Ben Bacarisse escreveu:
    Thiago Adams <thiago.adams@gmail.com> writes:

    On 22/03/2024 08:30, Stefan Ram wrote:
    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls
    "f( a )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then
    knows the length of "a". This is supposed to be less error prone
    than passing a pointer with a separate length argument.
    Of course, I immediately wondered whether one could implement
    such a "span" for C, and here's a draft:
    #include <stdio.h>
    #define SPAN_PARAM(x,a,n) x*a,size_t const n
    #define SPAN(a) a,(sizeof a/sizeof 0[a])
    void print( SPAN_PARAM( int, a, n ))
    { for( size_t i = 0; i < n; ++i )
    printf( "%lld: %d\n", i, a[ i ]); }
    int main( void )
    { int a[ 3 ]={ 4, 6, 8 };
    print( SPAN(a) ); }
    . But since C is another language, there are other forces at work,
    which means that the overall usability of such macros in C might not >>> make their definition and use worthwhile. Of course, the "smart" span >>> type in C++ surely can do more than my simple macros can do in C!


    (
    C++ proposals use new type<T> instead of qualifiers. This creates a big
    mess on the type system and incompatibility with C.
    I don't have idea how/why they do this constantly.
    )

    C does not need this for parameters since the current array syntax already >> cover that.

    void f(int n, int a[n])

    Although you can't rely on this anymore since it's now an optional part
    of the language.

    I think it is back in c23.
    But not vlas.

    ...
    C already have a syntax for pointer to array

    int (*)[2] p;

    I think you mean

    int (*p)[2];

    yes.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From fir@3:633/280.2 to All on Sun Mar 24 06:32:06 2024
    Stefan Ram wrote:
    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls
    "f( a )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then
    knows the length of "a". This is supposed to be less error prone
    than passing a pointer with a separate length argument.


    i wrote on such thing for years here - i name it "full array"

    i mean

    int a[20] is "full array" when a is a structure of int* to begoning and
    int* to end or length (there are natural two wersions and i tried both
    though the one with pointer+_size is maybe more handy)

    this foo(a) will pass this structure if a is full array - but this is to
    be done on language and compiler level

    what c got

    int a[20] //when a is only int*

    i name half-array





    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From Blue-Maned_Hawk@3:633/280.2 to All on Sun Mar 24 07:35:11 2024
    Stefan Ram wrote:

    Some people suggested to introduce a feature "span" (probably a
    type) into C++, so that when one has an int array "a" and calls "f( a
    )", the length of a is being transferred to "f", which "f"
    is defined using "void f(span<int> a)". The "span" in "f" then knows
    the length of "a". This is supposed to be less error prone than
    passing a pointer with a separate length argument.

    Of course, I immediately wondered whether one could implement such a
    "span" for C, and here's a draft:

    #include <stdio.h>

    #define SPAN_PARAM(x,a,n) x*a,size_t const n #define SPAN(a) a,(sizeof a/sizeof 0[a])

    void print( SPAN_PARAM( int, a, n ))
    { for( size_t i = 0; i < n; ++i )
    printf( "%lld: %d\n", i, a[ i ]); }

    int main( void )
    { int a[ 3 ]={ 4, 6, 8 };
    print( SPAN(a) ); }

    . But since C is another language, there are other forces at work,
    which means that the overall usability of such macros in C might not
    make their definition and use worthwhile. Of course, the "smart" span
    type in C++ surely can do more than my simple macros can do in C!

    You managed to inspire me to try my own hand at coming up with some macros
    for spannage in C. By means of the library of macros P99 and the power of C23, i ended up with this:

    #define span(...) typeof (__VA_ARGS__) *
    #define span_of(...) (((struct {const size_t length; typeof (__VA_ARGS__) members
    #define with_members(...) [P99_NARG(__VA_ARGS__)];})
    {P99_NARG(__VA_ARGS__), {__VA_ARGS__}}).members)
    #define span_length(...) (((struct {const size_t length; typeof (__VA_ARGS__[0]) members[];} *)&(((char *)(__VA_ARGS__))[-sizeof (size_t)]))->length)

    This is used as such:

    void f(const span(int) obj)
    {
    printf("%d, %d, %d, %zu", obj[1], obj[2], obj[5],
    span_length(obj));
    }

    int main(void)
    {
    span(int) the_span = span_of(int) with_members(1,2,3,4,5,6);
    printf("%d, %d, %d, %zu", the_span[1], the_span[2], the_span[5], span_length(the_span));
    return 0;
    }

    Now, you may notice that this, uh. doesn't actually work: the
    with_members macro breaks if you're initializing the array with members
    that have embedded commas in them. I tried to fix this, but my compiler claimed that P99's P99_REMOVE_PAREN macro doesn't exist even though it
    does.

    On a tangent, the way that the typeof operator works in C23 means that
    macros no longer have to worry about the fact that declarations such as
    int(*)(int) x;
    and
    int[3] y;
    don't work, meaning that they can accept any typename and use it raw
    without needing the invoker to make a typedef.

    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    The dark side of the C preprocessor is a path to many abilities, some considered unnatural.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Sun Mar 24 08:50:52 2024
    Thiago Adams <thiago.adams@gmail.com> writes:
    Em 3/22/2024 9:19 PM, Ben Bacarisse escreveu:
    Thiago Adams <thiago.adams@gmail.com> writes:
    [...]
    void f(int n, int a[n])
    Although you can't rely on this anymore since it's now an optional
    part of the language.

    I think it is back in c23.
    But not vlas.
    [...]

    Correct.

    From N1570 (the last public draft before C11):

    __STDC_NO_VLA__ The integer constant 1, intended to indicate that
    the implementation does not support variable length arrays or
    variably modified types.

    From N3220 (the first public draft of C26, essentially equivalent to C23):

    __STDC_NO_VLA__ The integer constant 1, intended to indicate that
    the implementation does not support variable length arrays with
    automatic storage duration. Parameters declared with variable
    length array types are adjusted and then define objects of
    automatic storage duration with pointer types. Thus, support for
    such declarations is mandatory.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    Working, but not speaking, for Medtronic
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From Ben Bacarisse@3:633/280.2 to All on Sun Mar 24 12:28:17 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Thiago Adams <thiago.adams@gmail.com> writes:
    Em 3/22/2024 9:19 PM, Ben Bacarisse escreveu:
    Thiago Adams <thiago.adams@gmail.com> writes:
    [...]
    void f(int n, int a[n])
    Although you can't rely on this anymore since it's now an optional
    part of the language.

    I think it is back in c23.
    But not vlas.
    [...]

    Correct.

    From N1570 (the last public draft before C11):

    __STDC_NO_VLA__ The integer constant 1, intended to indicate that
    the implementation does not support variable length arrays or
    variably modified types.

    From N3220 (the first public draft of C26, essentially equivalent to C23):

    __STDC_NO_VLA__ The integer constant 1, intended to indicate that
    the implementation does not support variable length arrays with
    automatic storage duration. Parameters declared with variable
    length array types are adjusted and then define objects of
    automatic storage duration with pointer types. Thus, support for
    such declarations is mandatory.

    Has C23 been ratified yet? The fact that there's a draft of C26
    suggests it has been, but the news passed me by.

    --
    Ben.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Sun Mar 24 13:15:59 2024
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Thiago Adams <thiago.adams@gmail.com> writes:
    Em 3/22/2024 9:19 PM, Ben Bacarisse escreveu:
    Thiago Adams <thiago.adams@gmail.com> writes:
    [...]
    void f(int n, int a[n])
    Although you can't rely on this anymore since it's now an optional
    part of the language.

    I think it is back in c23.
    But not vlas.
    [...]

    Correct.

    From N1570 (the last public draft before C11):

    __STDC_NO_VLA__ The integer constant 1, intended to indicate that
    the implementation does not support variable length arrays or
    variably modified types.

    From N3220 (the first public draft of C26, essentially equivalent to C23): >>
    __STDC_NO_VLA__ The integer constant 1, intended to indicate that
    the implementation does not support variable length arrays with
    automatic storage duration. Parameters declared with variable
    length array types are adjusted and then define objects of
    automatic storage duration with pointer types. Thus, support for
    such declarations is mandatory.

    Has C23 been ratified yet? The fact that there's a draft of C26
    suggests it has been, but the news passed me by.

    I don't believe it has.

    According to <https://www.open-std.org/jtc1/sc22/wg14/>, "WG14 has
    finished revising the C standard, under the name C23".

    N3219, published 2024-02-22, is the Draft International Standard.
    It's password-protected.

    N3220, published the same day, is the C2y draft. My understanding is
    that its content is very nearly indentical to N3219. I don't know what
    changes are possible or likely between N3219 and the upcoming C23
    standard.

    https://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    Working, but not speaking, for Medtronic
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From Ben Bacarisse@3:633/280.2 to All on Sun Mar 24 22:11:50 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
    ....
    Has C23 been ratified yet? The fact that there's a draft of C26
    suggests it has been, but the news passed me by.

    I don't believe it has.

    According to <https://www.open-std.org/jtc1/sc22/wg14/>, "WG14 has
    finished revising the C standard, under the name C23".

    N3219, published 2024-02-22, is the Draft International Standard.
    It's password-protected.

    N3220, published the same day, is the C2y draft. My understanding is
    that its content is very nearly indentical to N3219. I don't know what changes are possible or likely between N3219 and the upcoming C23
    standard.

    https://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log

    Thanks.

    --
    Ben.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Lawrence D'Oliveiro@3:633/280.2 to All on Mon Mar 25 11:53:19 2024
    On Sat, 23 Mar 2024 19:15:59 -0700, Keith Thompson wrote:

    N3219, published 2024-02-22, is the Draft International Standard.
    It's password-protected.

    Didn’t take much of a search to find the password ...

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)