gcc: pointer to array

S

S.Tobias

In comp.lang.c Netocrat said:
Right, my concept of lvalue was slightly out. Non-modifiable being for
example arrays and structs.

I'm not sure it's that simple with storage for lvalues. Take `register'
variables for an example, or pointers to objects whose lifetime has
finished (dereferencing such a pointer is an lvalue, whether
the object exists or not).

Consider also this example:

struct s { int a[1]; };
struct s f(void);

f().a[0] = 7; //UB

The expression on the left is clearly a modifiable lvalue.
But does it take any storage? I think C++ is more verbose about
temporaries; they can be optimized out, which is unspecified.
I don't think C even has an idea of a temporary.

OTOH, f().a decays into a pointer to its first element, therefore
the array the pointer points to must be an object, therefore it
must (temporarily) take some storage. Is that a right conclusion?
 
R

Richard Bos

Netocrat said:
Right, my concept of lvalue was slightly out. Non-modifiable being for
example arrays and structs.

Nope, only arrays, not structs. Structs can be assigned to. (You might
be confusing this with the lack of struct constants in C89. This lack
means that, if you want to assign something to a struct, in must be
another struct; there's no such thing as i=4 for structs, only i=j. Or
perhaps by the possibility of structs being incomplete (see below); but
this isn't true for structs in general.)
Other non-modifiable lvalues are incomplete types (unfinished
variable-length arrays, declared but not yet defined structs, etc.),
const objects (no surprise there), or structs or unions with
non-modifiable members.

Richard
 
F

Fabio Alemagna

Andrey said:
That's true. But in my message I'm talking about the difference between
the way single- and multi-dimensional arrays are addressed. No pointers
involved (multi-indirectioned or not). You for some reason start talking
about pointers. Why?

Want an honest answer? I have no idea, sorry :-| Dunno what the heck I
was thinking about :)
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Fabio said:
CBFalconer said:
That is to say, int foo[10][20] doesn't decay to int **.



Which is because there are no multi-dimensioned arrays in C,


Of course there are, you quoted one above.

Nope. That's not a multi-dimensional array.

That's an array of 10 elements, each element being an array of 20 ints.

- --
Lew Pitcher
IT Specialist, Enterprise Data Systems,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed are my own, not my employers')
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFC1rT/agVFX4UWr64RAmMZAJ4kxJO5L13YdlEfpNylxup8GzOiAQCg0eTU
K9j0Yat8G0REQ52iU7GJ5QU=
=1ba/
-----END PGP SIGNATURE-----
 
A

Andrey Tarasevich

Lew said:
Nope. That's not a multi-dimensional array.

That's an array of 10 elements, each element being an array of 20 ints.
...

So? "Multi-dimensional array" is just a concept. There are different ways to
implement this concept. Can anyone please explain to me, why the C-language's
approach to multidimensional arrays does not qualify as a valid implementation
of that concept? I hear it again and again, but somehow nobody is ever able to
come up with a more-or-less rational basis for such statement.
 
F

Fabio Alemagna

Lew said:
That is to say, int foo[10][20] doesn't decay to int **.

Which is because there are no multi-dimensioned arrays in C,

Of course there are, you quoted one above.

Nope. That's not a multi-dimensional array.

That's an array of 10 elements, each element being an array of 20 ints.

Precisely, a multidimensional array.
 
A

Alexei A. Frounze

Andrey Tarasevich said:
Lew Pitcher wrote:

Guys, if there's nothing to add to my initial post (I think so as I have no
further questions on the subject), you may exclude alt.os.development from
the target.

Thanks,
Alex
 
C

CBFalconer

Fabio said:
Lew Pitcher wrote:
(and somebody foolishly stripped all the attributions)
That is to say, int foo[10][20] doesn't decay to int **.

Which is because there are no multi-dimensioned arrays in C,

Of course there are, you quoted one above.

Nope. That's not a multi-dimensional array. That's an array of
10 elements, each element being an array of 20 ints.

Precisely, a multidimensional array.

No, it is an array of 200 ints, which can be mapped into an
array[10] of array[20] of int. It can also be mapped into an
array[20] of array[10], or array[2] of array[100], etc. The
notation is just a means of getting the compiler to do some of the
arithmetic for you, and the technique fails all too often,
especially when you don't understand what is going on.

The memory people have gone to a lot of trouble to present that
memory as a linear array. You wouldn't like it if you had to deal
with the reality, involving row and column strobes, chip selects,
etc. In the old days you also had to deal with inhibit current.
 
P

Peter Nilsson

S.Tobias said:
You raise UB here: (const char*) and (char*) types are
not compatible - you cannot pass incompatible arguments
to a function call (cf. 6.5.2.2#6).

C99 has different wording from N869.

[It looks like it's not valid C90 though.]
 
F

Fabio Alemagna

CBFalconer said:
No, it is an array of 200 ints,

You can't change your definition each time you answer. Before you said
it's an array of an array, now you say it's just an array, 'cause that
suits your goal better now.
which can be mapped into an
array[10] of array[20] of int. It can also be mapped into an
array[20] of array[10], or array[2] of array[100], etc.

So what? That's an implementation detail. To make you happy the 2nd
dimension arrays should have been put where, exactly?
The
notation is just a means of getting the compiler to do some of the
arithmetic for you, and the technique fails all too often,
especially when you don't understand what is going on.

Please, can you give examples about such failures? I've never
encountered any.
The memory people have gone to a lot of trouble to present that
memory as a linear array. You wouldn't like it if you had to deal
with the reality, involving row and column strobes, chip selects,
etc. In the old days you also had to deal with inhibit current.

Hm? What's got that to do with multidimensional arrays in C?

Ok, let's do something constructive: please, explain what would be a
"real" multidimensional array.
 
N

Netocrat

Lew said:
That is to say, int foo[10][20] doesn't decay to int **.

Which is because there are no multi-dimensioned arrays in C,

Of course there are, you quoted one above.

Nope. That's not a multi-dimensional array.

That's an array of 10 elements, each element being an array of 20 ints.

Precisely, a multidimensional array.

This is easily settled by the standard.

N869, 6.7.5.2:

When several ``array of'' specifications are adjacent, a multidimensional
array is declared.

There's similar language in the C89 draft.
 
N

Netocrat

I'm not sure it's that simple with storage for lvalues. Take `register'
variables for an example, or pointers to objects whose lifetime has
finished (dereferencing such a pointer is an lvalue, whether the object
exists or not).

The C89 draft says:

"The unary * operator denotes indirection. If the operand points to ... an
object, the result is an lvalue designating the object... If an invalid
value has been assigned to the pointer, the behavior of the unary *
operator is undefined."

Since in this case the pointer has an invalid value it would be illegal to
dereference it; the question of whether or not the result would be an
lvalue is moot.
Consider also this example:

struct s { int a[1]; };
struct s f(void);

f().a[0] = 7; //UB

The expression on the left is clearly a modifiable lvalue.

Not so clearly according to gcc. I get:
"ISO C90 forbids subscripting non-lvalue array".
But does it take any storage? I think C++ is more verbose about
temporaries; they can be optimized out, which is unspecified.
I don't think C even has an idea of a temporary.

It doesn't occur in the context of variable storage in either draft.
OTOH, f().a decays into a pointer to its first element, therefore
the array the pointer points to must be an object, therefore it
must (temporarily) take some storage. Is that a right conclusion?

If f() were a modifiable lvalue which in this context it does not appear
to be, then I would see nothing wrong with your reasoning. However given
that there's no means of later reading back the assignment, it's really a
no-op and again the question is moot: nothing changes whether the
assignment occurs or not. Perhaps that's why C99 allows it.
 
N

Netocrat

Nope, only arrays, not structs. Structs can be assigned to. (You might
be confusing this with the lack of struct constants in C89.

It was thoughtlessness rather than confusion, but see below.
This lack
means that, if you want to assign something to a struct, in must be
another struct; there's no such thing as i=4 for structs, only i=j.

You seem to imply that something similar to i=4 where i is a struct is
possible in C99, which I haven't come across before.
Or
perhaps by the possibility of structs being incomplete (see below); but
this isn't true for structs in general.)
Other non-modifiable lvalues are incomplete types (unfinished
variable-length arrays, declared but not yet defined structs, etc.),

I'm with you on all of those bar the last. Surely by the time you attempt
to access a struct variable as an lvalue, the struct must have been
defined?

<snip>
 
L

Lukaszp

The problem is that array itself is a pointer to it's beginning so then
writing &aInt3 would give you pointer to pointer to an array. Solution
is to pass only aInt3 to your function.

Another thing is that const modifier. It tells you that this function
is not going to change received pointer i.e. set it to another array.
And after a function call it will point to the same thing it was
pointing befeore the call.
 
R

Richard Heathfield

[Followups set to comp.lang.c]
The problem is that array itself is a pointer to it's beginning so then

Not quite. The array itself is an array. The /value/ of the array, when that
array's name is used in a value context, is the address of the first
element.
writing &aInt3 would give you pointer to pointer to an array. Solution
is to pass only aInt3 to your function.

The declaration in question was:

int aInt3[5] = {0,1,2,4,9};

When you write &aInt3, you're actually getting the address of the array (the
array is not being used in a value context here); the type is int (*)[5],
i.e. a pointer to an array, not a pointer to a pointer to an array as you
incorrectly claimed. (This is a tricky area - it's intensely logical, but
C's logic doesn't always map perfectly to programmers' first-cut instinct!)
 
P

pete

Richard said:
The /value/ of the array, when that
array's name is used in a value context, is the address of the first
element.

I see you have the word /value/ highlighted.

Operations which result in pointers to the operand,
don't operate on the value of the operand.

The value of &i doesn't depend on the value of i.

The value of (array + 0) doesn't depend on the contents of the array,
though I'll admit I can't recall any consensus as to what,
if anything, "value" means when applied to an array.
 
R

Richard Heathfield

Lukaszp said:
Ok. Thanks. did i have right with the const modifier?

Funny you should mention that. No, you didn't have it right. :-(

Sorry, but that's life. const int (*p)[5] means "pointer to array of 5 const
ints", not "const pointer to array of 5 ints".

Apologies for not noticing that in my first reply.
 
R

Richard Heathfield

pete said:
I see you have the word /value/ highlighted.
Correct.


Operations which result in pointers to the operand,
don't operate on the value of the operand.

Correct as far as I can see, without spilling ISO ketchup all over the
thread.
The value of &i doesn't depend on the value of i.

Correct, although of course the value of i can depend on &i in at least one
case.
The value of (array + 0) doesn't depend on the contents of the array,
though I'll admit I can't recall any consensus as to what,
if anything, "value" means when applied to an array.

It's The Rule, a la CT. In a value context, the name of an array decays to a
pointer to the first element of that array. So, effectively, the value of
an array is a pointer to its first element, n'est-ce-pas?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,181
Messages
2,570,970
Members
47,536
Latest member
VeldaYoung

Latest Threads

Top