Re: Pointer arithmetics in 2D arrays




"Pierre Asselin" <pa@xxxxxxxxxxxxxxxxxxxxx> ha scritto nel messaggio
news:f27iuq$oki$1@xxxxxxxxxxxxxxxxxxxx
Richard Heathfield <rjh@xxxxxxxxxxxxxxx> wrote:
Army1987 said:

print_square_matrix(*matrix, 3);

matrix has type int[3][3], which decays to int(*)[3] when used in a
value context. So *matrix has type int[3] - but you use this in a value
context too, so it becomes int *. That's legal to pass to
print_square_matrix, which takes int *. But in print_square_matrix, you
are, strictly speaking, breaking the rules. Why? Well, you pass a
pointer that points to the first element in an array of three ints, but
you roll through nine ints in your function. Therefore, you're
overstepping the bounds of an array.

Such a strict interpretation would cripple the use of C in numerical
computations. I don't think that was the intent, based in part on a
a similar example I noticed in the C99 Rationale v5.10, end of
section 6.7.5.3 .

<quote>
void g(double *ap, int n)
{
double (*a)[n] = (double (*)[n]) ap;
/* ... */ a[1][2] /* ... */
}

[ ... ] the function g can be called as in

{
double x[10][10];
g(&x[0][0], 10);
}
</quote>

The cited example has "&x[0][0]" as opposed to "*matrix" in the
orignal post, but that seems like a very subtle distinction. In
the Rationale code, "x[0][0]" is a mere scalar and "&x[0][0]" is
its address, but it is clear that g() is allowed to treat this
address as the start of an array of 100 doubles. (The example
goes on to show how to view said array as a two-dimensional object
by means of a VLA, but that's beside the point here.)

So in my view, the OP's code is de-facto valid C (C89 since he
doesn't use a VLA). If the OP needs to survive a code review, he
could write

print_square_matrix(&matrix[0][0], 3);

and cite the C99 rationale 6.7.5.3 in a comment.
Here the Standard quietly whispers what the behaviour is, but officially
says it is undefined. Annex J, under "Undefined behaviour":
An array subscript is out of range, even if an object is apparently
accessible with the

given subscript (as in the lvalue expression a[1][7] given the declaration
int

a[4][5]) (6.5.6).

(I wasn't aware that there has been an implementation which actually checks
array bounds, since I thought that would defeat the purpose why array
overflow was declared UB in the first place (i.e. speeding up run time by
trusting the program). But if there is one, I understand why even
overflowing the innermost array is UB.)


.



Relevant Pages

  • (patch for Bash) regex case statement
    ... Following up on my previous patch for regex conditional tests, ... /* Return an array of strings; ... int dollarflag, zeropad, compareflag; ... SHELL_VAR *var; ...
    (comp.unix.shell)
  • Re: [PATCH v3 2/2] bsearch: prevent overflow when computing middle comparison element
    ... overflow situation when computing the middle element for comparison. ... maximum int value. ... approaches the maximum unsigned int ... at the highest extreme of the array. ...
    (Linux-Kernel)
  • Re: Strategy or Iterator?
    ... It would be possible to write a class that returns the variations ... GNU General Public License for more details. ... protected CombinatoricOperator(Telements, int r) { ... An integer array backing up the original one to keep track of the ...
    (comp.lang.java.programmer)
  • (patch for Bash) regex conditional tests
    ... 'regex' are returned in array variable SUBMATCH. ... Skipping of positional parameters, array elements, string ... int dollarflag, zeropad, compareflag; ... SHELL_VAR *var; ...
    (comp.unix.shell)
  • Re: attempting an actual game...
    ... >>> and inflexible by the absurd decision to use a bit array for square ... as then one has 8 bits in which to store a color and a few flags ... Using a 2D int (or, ... > Change direction and you may eventually complete a game. ...
    (comp.games.development.programming.misc)