• Arrays

    From Stefan Ram@21:1/5 to All on Sun Sep 29 11:33:33 2024
    Alright, so I've got a triple whammy of questions coming at me.
    It's about this program I've been tinkering with.

    #include <stdio.h>
    int main()
    { char const abc[] = "abcdefhijklmnopqrstuvwxyz";
    char const * const p = abc + 3;
    char const( * const def )[] =( char const( * const )[] )p;
    printf( "%c\n",( *def )[ -3 ]); }

    1st

    First off, I'm getting this warning that's throwing me for a loop:

    main.c: In function 'main':
    main.c:7:32: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
    7 | char const( * const def )[] =( char const( * const )[] )p;
    | ^

    So I'm wondering: How can I dodge this discarding the constness
    warning?

    2nd

    Then I'm hit with another warning:

    main.c:7:3: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
    7 | char const( * const def )[] =( char const( * const )[] )p;
    | ^~~~

    What's this warning trying to tell me?

    3rd

    But the real head-scratcher is that "-3" in the last line.
    On paper, we're crunching numbers to get the address of
    a spot before the object (the object being "( *def )"),
    so technically we're in undefined behavior territory.

    But here's the kicker - we know that spot is still chilling in the
    "abc" array. Does the language standard have any loopholes that
    might save our bacon here and make this not undefined after all?

    TIA!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Stefan Ram on Sun Sep 29 14:45:14 2024
    On 29 Sep 2024 11:33:33 GMT
    [email protected] (Stefan Ram) wrote:

    Alright, so I've got a triple whammy of questions coming at me.
    It's about this program I've been tinkering with.

    #include <stdio.h>
    int main()
    { char const abc[] = "abcdefhijklmnopqrstuvwxyz";


    Are three lines above sufficient to conclude that despite fabulously
    extended vocabulary we are dealing with the same Stefan Ram of old?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Stefan Ram on Sun Sep 29 10:04:00 2024
    On 9/29/24 07:33, Stefan Ram wrote:
    Alright, so I've got a triple whammy of questions coming at me.
    It's about this program I've been tinkering with.

    #include <stdio.h>
    int main()
    { char const abc[] = "abcdefhijklmnopqrstuvwxyz";
    char const * const p = abc + 3;
    char const( * const def )[] =( char const( * const )[] )p;
    printf( "%c\n",( *def )[ -3 ]); }

    1st

    First off, I'm getting this warning that's throwing me for a loop:

    main.c: In function 'main':
    main.c:7:32: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
    7 | char const( * const def )[] =( char const( * const )[] )p;
    | ^>
    So I'm wondering: How can I dodge this discarding the constness
    warning?

    I'm afraid I can't help you with that.

    2nd

    Then I'm hit with another warning:

    main.c:7:3: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
    7 | char const( * const def )[] =( char const( * const )[] )p;
    | ^~~~

    What's this warning trying to tell me?

    Section 6.5p4 lists the cases where you take a pointer to an object with
    a given effective type, convert it to a pointer to a different type, and dereference that converted pointer with defined behavior. The conversion
    you do here isn't one of the ones listed.
    That doesn't mean that your code has undefined behavior. You only access
    the memory using (*def)[-3], which is an lvalue of character type, which
    is not only the same as the effective type of that memory, but is also
    one of the options listed in 6.5p4. However, in general, the result of
    the conversion could be used in ways that do violate 6.5p4. I don't see
    how you could do so in this case, because you can't use a pointer to an
    array type to directly access the memory - you have to subscript it to
    do so. There's a reason why this is a warning rather than a fatal error.

    3rd

    But the real head-scratcher is that "-3" in the last line.
    On paper, we're crunching numbers to get the address of
    a spot before the object (the object being "( *def )"),
    so technically we're in undefined behavior territory.

    But here's the kicker - we know that spot is still chilling in the
    "abc" array. Does the language standard have any loopholes that
    might save our bacon here and make this not undefined after all?

    (*def)[-3] is defined as equivalent to *(*def - 3), so this involves subtracting an integer value from a pointer value. The relevant rules are:

    "If the pointer operand points to an element of an array object, and the
    array is large enough, the result points to an element offset from the
    original element such that the difference of the subscripts of the
    resulting and original array elements equals the integer expression.
    In other words, if the expression P points to the i-th element of an
    array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N
    (where N has the value n) point to, respectively, the i + n-th and i −
    n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the
    expression (P)+1 points one past the last element of the array object,
    and if the expression Q points one past the last element of an array
    object, the expression (Q)-1 points to the last element of the array
    object. If the pointer operand and the result do not point to elements
    of the same array object or one past the last element of the array
    object, the behavior is undefined." (6.5.6p9)

    Note that the limits are based solely upon the array containing the
    element that the pointer points at; how the pointer itself is declared
    is not relevant. In this case, you can safely move that pointer as far
    back as the "a" in abc[], and as far forward as the the null character
    at the end of abc, and access the pointed-at character. You can also
    advance it one past the null character, but the resulting pointer value
    cannot be dereferenced. It can be used for pointer comparisons, which is
    the single most common use of one-past-the-end pointer values.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Stefan Ram on Sun Sep 29 16:11:08 2024
    On 2024-09-29, Stefan Ram <[email protected]> wrote:
    Alright, so I've got a triple whammy of questions coming at me.
    It's about this program I've been tinkering with.

    #include <stdio.h>
    int main()
    { char const abc[] = "abcdefhijklmnopqrstuvwxyz";
    char const * const p = abc + 3;
    char const( * const def )[] =( char const( * const )[] )p;
    ^^^^^^^^^^^^^^^^^^^^^^^^^
    ]
    This is a const pointer to an array (of unknown size) to const char.

    printf( "%c\n",( *def )[ -3 ]); }

    1st

    First off, I'm getting this warning that's throwing me for a loop:

    main.c: In function 'main':
    main.c:7:32: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
    7 | char const( * const def )[] =( char const( * const )[] )p;

    The problem is that def is a pointer to an array of const char.

    The const char elements are const qualified, but the array type is not!

    That's why a qualifier is being stripped in the cast.

    So I'm wondering: How can I dodge this discarding the constness
    warning?

    I would say, don't work with pointers to arrays.

    There is no way to declare a const array in declarator syntax.
    You must create a typedef name N for the array type and then
    refer to it as const N.

    2nd

    Then I'm hit with another warning:

    main.c:7:3: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
    7 | char const( * const def )[] =( char const( * const )[] )p;
    | ^~~~

    What's this warning trying to tell me?

    That you're banging your head against array-pointer-const corner cases
    in the C language.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Sun Sep 29 18:33:01 2024
    Michael S <[email protected]> writes:
    On 29 Sep 2024 11:33:33 GMT
    [email protected] (Stefan Ram) wrote:

    Alright, so I've got a triple whammy of questions coming at me.
    It's about this program I've been tinkering with.

    #include <stdio.h>
    int main()
    { char const abc[] = "abcdefhijklmnopqrstuvwxyz";


    Are three lines above sufficient to conclude that despite fabulously
    extended vocabulary we are dealing with the same Stefan Ram of old?


    I have my doubts. I think someone is playing with an AI that doesn't
    realize that Stefan is German.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)