Re: Arrays

Liste des GroupesRevenir à cl c 
Sujet : Re: Arrays
De : jameskuyper (at) *nospam* alumni.caltech.edu (James Kuyper)
Groupes : comp.lang.c
Date : 29. Sep 2024, 15:04:00
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <vdbmog$1p25i$1@dont-email.me>
References : 1
User-Agent : Mozilla Thunderbird
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.



Date Sujet#  Auteur
29 Sep 24 * Arrays4Stefan Ram
29 Sep 24 +- Re: Arrays1Michael S
29 Sep 24 +- Re: Arrays1James Kuyper
29 Sep 24 `- Re: Arrays1Kaz Kylheku

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal