[comp.lang.c] Address of Array

jack@citcom.UUCP (Jack Waugh) (11/30/87)

It recently occurred to me that there is no syntax to take the
address of an array, although an expression of that type can be
derived from an array of arrays, and a variable of that type
can be declared.  The obvious syntax, &a, is incorrect because
you can only & an lvalue.

[Neophytes, please don't tell the world the name of an array denotes
its address.  It denotes the address of the first element, which
does not mean the same thing if you add an integer to it.]

gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/30/87)

In article <126@citcom.UUCP> jack@citcom.UUCP (Jack Waugh) writes:
>It recently occurred to me that there is no syntax to take the
>address of an array...

Arrays are not first-class citizens in C.  Nevertheless, the proposed
ANSI standard for C permits &array.

decot@hpisod2.HP.COM (Dave Decot) (11/30/87)

> It recently occurred to me that there is no syntax to take the
> address of an array, although an expression of that type can be
> derived from an array of arrays, and a variable of that type
> can be declared.  The obvious syntax, &a, is incorrect because
> you can only & an lvalue.
> 
> [Neophytes, please don't tell the world the name of an array denotes
> its address.  It denotes the address of the first element, which
> does not mean the same thing if you add an integer to it.]

I screamed in horror when I read in K&R of this design botch.
This is the fundamental reason you can now take any type (including
a structure containing an array!!) and assign to it, pass it to and return it
from functions, EXCEPT an array type.

However, I propose the syntax "a[]" to refer to an lvalue which is the
entire array a, and "&(a[])" (sorry, that's the precedence) to signify
the address of the entire array a.  

In order to declare a formal parameter of an array type, one
would have to supply the dimension in the brackets, since otherwise
the size would be unknown:

    int (bubblesort(array, n))[MAX]
    int array[MAX], n;
    {
	int i, done, tmp, newarray[MAX];
		 
	newarray[] = array[];	  /* copy the value of array to newarray */
				  /* gratuitous, yes, but this is an example */

	do
	{
	    done = 1;

	    for (i = 0; i < n-1; i++)
		if (newarray[i] > newarray[i+1])
		{
		   tmp = newarray[i];
		   newarray[i] = newarray[i+1];
		   newarray[i+1] = tmp;
		   done = 0;
		}

	} while (!done);
		   
	return newarray[];	/* return the whole array */
    }

Dave Decot
hpda!decot

throopw@xyzzy.UUCP (Wayne A. Throop) (12/02/87)

> jack@citcom.UUCP (Jack Waugh)
> It recently occurred to me that there is no syntax to take the
> address of an array, although an expression of that type can be
> derived from an array of arrays, and a variable of that type
> can be declared.  The obvious syntax, &a, is incorrect because
> you can only & an lvalue.

Correct.  This deficency is fixed in the draft ANSI standard for C,
X3J11, by making objects of array type non-modifiable lvalues.  See
section 3.2.2.1 of the November 9th version of the draft standard for
an explanation of what goes on for constructs such as (&array).

--
"Suddenly I feel so... sapient."
                        --- Fluffy
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/02/87)

In article <2550034@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
>However, I propose ...
>In order to declare a formal parameter of an array type, one
>would have to supply the dimension in the brackets, ...

The X3J11 committee considered fixing the design of arrays in C to be
full-fledged data object types, but soon realized that doing so would
invalidate mountains of existing code.  Feel free to fix it when you
design la)) { never

pjh@mccc.UUCP (Peter J. Holsberg) (12/02/87)

OK - perhaps you had better tell us neophytes what you mean by the
address of an array!

-- 
Peter Holsberg				UUCP: {rutgers!}princeton!mccc!pjh
Technology Division			CompuServe: 70240,334
Mercer College				GEnie: PJHOLSBERG
Trenton, NJ 08690			Voice: 1-609-586-4800

throopw@xyzzy.UUCP (Wayne A. Throop) (12/03/87)

> pjh@mccc.UUCP (Peter J. Holsberg)
> OK - perhaps you had better tell us neophytes what you mean by the
> address of an array!

Same as address of anything else.  It is an address which, when
indirected, yields an array, and when "N" is added to it, yields the
address of an array which is itself a member of an array "N" elements
away from the array yielded by an indirection.

A pointer to an integer array of 10 elements is declared by

        int (*a)[10];

and could be used like so

        a[N]            /* Nth array of ten ints away from (*a) */
        (*a)[N]         /* Nth int in the array pointed to by a */
        a[N][M]         /* Mth int in the Nth array */
        (*(a+N))[M]     /* same as a[N][M] */

What could be simpler?

--
Another interesting facet of ninja was the use of magic. They had
a reputation as sorcerors and wizards who could fly and hypnotize, and
walk through walls, and get away with huge deductions on their taxes.
    --- Bruce Israel martial-arts-request@brillig
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw

karl@haddock.ISC.COM (Karl Heuer) (12/04/87)

In article <2550034@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
>I propose the syntax "a[]" to refer to an lvalue which is the entire array a,

Okay so far.

>and "&(a[])" to signify the address of the entire array a.

Unnecessary, since ANSI has blessed the simpler syntax "&a".

>In order to declare a formal parameter of an array type, one would have to
>supply the dimension in the brackets, since otherwise the size would be
>unknown:
>    int (bubblesort(array, n))[MAX]  int array[MAX], n;  { ... }

Nice try, but a formal argument declared "int array[MAX]" is already legal,
and it means the wrong thing.  (It's a backwards way of declaring a pointer.
Cf. "char *argv[]", which really means "char **argv"; this is true even if you
specify an explicit size.)

As of the Oct86 Draft (and presumably the latest one, too), this was to be
true even in prototype notation:
    void foo(int array[MAX]) { ... }
doesn't do the "right thing" either.  This is the first thing that needs to be
changed; otherwise it will be nearly impossible to ever make arrays into
first-class datatypes.

The very first step, then, must be to ask ANSI to *forbid* array-typed formal
arguments (as opposed to having them denote pointers).  This would not break
any existing code, because it would only affect prototypes, not old-style
declarations.

It's too late for me to have any influence on this decision, but if any of you
have already submitted official proposals on this issue, you may still have a
chance to stop ANSI from digging itself into this hole.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

sarima@gryphon.UUCP (12/05/87)

In article <163@mccc.UUCP> pjh@mccc.UUCP (Peter J. Holsberg) writes:
>
>OK - perhaps you had better tell us neophytes what you mean by the
>address of an array!
>
Alright, I hope I can express this clearly. From the context in of the
original article, the "address of an array" is a pointer to an "entire"
array, rather than just to the first element of it. That is it is a
pointer to an object of size sizeof(array) rather than an object of
size sizeof(array[0]), thus adding one to such a pointer will result
in a pointer to the next array object rather than the next element of
the current array. To put this as a 'C' type declaration: a pointer
to an array is of type: BASETYPE (*array_ptr)[ARRAYSIZE];

The most common way to get such a thing is to declare a two dimensional
array and then write an expression like 'array[n]', with only one
subscript. This evaluates to a pointer to the first sub-array of the
two dimensional array.


I hope I have not confused you too much with this rambling description:-)

ncbauers@ndsuvax.UUCP (Michael Bauers) (12/05/87)

In article <1854@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <2550034@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
>>I propose the syntax "a[]" to refer to an lvalue which is the entire array a,
>Okay so far.
>>and "&(a[])" to signify the address of the entire array a.
>Unnecessary, since ANSI has blessed the simpler syntax "&a".

	Two questions.

	1) I hate to sound picky but isn't &(a[]) the address of the array's
	   When you say address of the entire array it sounds like you mean
	   the address of the first element in the array.  The convention as I
	   understand it is to talk about it as you would in machine language.
	   So isn't the original System V C complier standard also to refer
	   to the address of the array's address &a.
	2) When will the proposed ANSI standard be avaiable?  When I interned
	   for Northern Telecom, I was in a class on 'C' where the instructor
	   mentioned this standard.  It sounded like a good idea to me.  In
	   this standard will a structures address, or the entire structure
	   be passed.  I am not sure I like the fact that the entire structure
	   is passed in our verion of C here.  It seems that any thing more
	   complex than a simple variable should have its address not its
	   contents passed.

levy@ttrdc.UUCP (Daniel R. Levy) (12/08/87)

In article <532@ndsuvax.UUCP>, ncbauers@ndsuvax.UUCP (Michael Bauers) writes:
>In article <1854@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>>In article <2550034@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
>>>I propose the syntax "a[]" to refer to an lvalue which is the entire array a,
>>Okay so far.
>>>and "&(a[])" to signify the address of the entire array a.
>>Unnecessary, since ANSI has blessed the simpler syntax "&a".
>
>	1) I hate to sound picky but isn't &(a[]) the address of the array's
		[first element?] -- drl
>	   When you say address of the entire array it sounds like you mean
>	   the address of the first element in the array.  The convention as I
>	   understand it is to talk about it as you would in machine language.
>	   So isn't the original System V C complier standard also to refer
>	   to the address of the array's address &a.

(PLEASE guys, be easy on this fellow.  Keep your fangs to yourself.  Down
boy!  DOWWNN BOY!!  [Grrrrrrrrr...])

In C, the usage of an "address" connotes more than mere location; the type of
the address also connotes the size of the object being addressed.  This size
comes into play when the address is incremented or decremented by an integral
value, or when the difference is taken between it and another address of the
same type.  The increment or decrement is taken to be in units of the type
of object pointed to by the address.  Likewise, the difference is taken to be
in units of the type of object pointed to.  The type of object addressed
may of course be a aggregate data type such as an array or struct just as
well as it could be a simple data type like int or char.
-- 
|------------Dan Levy------------|  Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
|         an Engihacker @        |  	<most AT&T machines>}!ttrdc!ttrda!levy
| AT&T Computer Systems Division |  Disclaimer?  Huh?  What disclaimer???
|--------Skokie, Illinois--------|

cl@dlhpedg.co.uk (Charles Lambert) (12/08/87)

In article <422@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes:
>> pjh@mccc.UUCP (Peter J. Holsberg)
>> OK - perhaps you had better tell us neophytes what you mean by the
>> address of an array!
>
>Same as address of anything else.  It is an address which, when
>indirected, yields an array, and when "N" is added to it, yields the
>address of an array which is itself a member of an array "N" elements
>away from the array yielded by an indirection.
> 
> [ several abstruse observations ]
>
>What could be simpler?

Well, several other forms of explanation, I guess.  This one confused me,
and I *understand* the address of an array. (Just teasing)

To put it another way....

Any object, of any type (integer, structure, array, etc.), has an address.
Usually, if it is an object that occupies several words of memory, it is the
address at which it begins. (Compiler theorists may be itching to tell me it
might mean something else entirely; let's keep this simple.)  The address of
an object is the compiler's handle for manipulating it.   You think of an
object by its name; the compiler "thinks" of it by its address.

The "address of an array" is the address that the compiler uses to access
that array and to calculate the position of any element in the array.

In C,  the address of an array is the same as the address of its first
element (array[0]).  If you want to set up a pointer to the array, you
get its address simply by naming it. Hence:

	pa = array;	/* pa now contains the address of "array" */

which is exactly the same as

	pa = &array[0]; /* "&" means "address of", so pa contains the
				address of element [0] of "array" */

Now this is a slight quirk in C - the name of the array being a synonym for
its address;  for any other object (notably a struct) that is not true.  If
you want the address of a structure you must write

	ps = &mystruct;	/* NOT ps = mystruct */

So we get back to the discussion from whence we came: why can't we be
consistent and get the address of an array by

	pa = &array;	?

To which the answer is:  you can, with some compilers.

[Further reading: The C Programming Language; Kernighan & Ritchie; pp.93-95]
--------------------------
Charles Lambert

ncbauers@ndsuvax.UUCP (Michael Bauers) (12/10/87)

	I must learn to write better, people keep telling me that with
a pointer is associated a type.  I know this...I program in C.  What I
was objecting to was when someone said 'address of array.'  What they
had meant to say I think was 'The adress of the array's pointer.'  I was
just noting that this was confusing.  I was confused anyway.  The article
I was responding to was talking about taking the address of an array.  The
address of the array a[10] is just a.  The address of the first element
is also a (for single dimension arrays).  The first element is *a.  But
the address of the array's pointer (what this person wanted to know)
should be &a.

marty1@houdi.UUCP (M.BRILLIANT) (12/12/87)

In article <555@ndsuvax.UUCP>, ncbauers@ndsuvax.UUCP (Michael Bauers) writes:
> The
> address of the array a[10] is just a.  The address of the first element
> is also a (for single dimension arrays).  The first element is *a.  But
> the address of the array's pointer ... should be &a.

Huh?  I tried writing a C program on UNIX(tm ATT) that referenced &a,
and got the message "warning: & before array or function: ignored."
That says there's no such thing as &a.

M. B. Brilliant					Marty
AT&T-BL HO 3D-520	(201)-949-1858
Holmdel, NJ 07733	ihnp4!houdi!marty1

karl@haddock.ISC.COM (Karl Heuer) (12/12/87)

In article <555@ndsuvax.UUCP> ncbauers@ndsuvax.UUCP (Michael Bauers) writes:
>But the address of the array's pointer (what this person wanted to know)
>should be &a.

Are you saying that "&a" should mean "&(&a[0])"?  This doesn't make sense, as
"&a[0]" is not an lvalue.  The original question really was talking about the
address of an entire array entity (which differs from the address of the first
element in exactly the same way that the address of a structure differs from
the address of its first member), and this is exactly the problem that X3J11
has fixed by legalizing "&a".

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

lvc@tut.cis.ohio-state.edu (Lawrence V. Cipriani) (12/12/87)

In article <1442@houdi.UUCP>, marty1@houdi.UUCP (M.BRILLIANT) writes:
> 
> Huh?  I tried writing a C program on UNIX(tm ATT) that referenced &a,
> and got the message "warning: & before array or function: ignored."
> That says there's no such thing as &a.
> 
> M. B. Brilliant					Marty

This is like taking the address of a constant, say &0435241250,
which of course is silly.
I have been programming in C for 5 1/2 years and I've never needed
to take the address of an array (except via &a[0], or just a).
Why do programmers want to do this?  Whats the point?  Do other
languages let you do this?  What is the advantage?  I can't see any.
Please enlighten me.

-- 
	Larry Cipriani AT&T Network Systems at
	cbosgd!osu-cis!tut!lvc Ohio State University

c188-bl@katerina.uucp (Steven Brian McKechnie Sargent) (12/12/87)

In article <1949@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <555@ndsuvax.UUCP> ncbauers@ndsuvax.UUCP (Michael Bauers) writes:
>>But the address of the array's pointer (what this person wanted to know)
>>should be &a.
>
>Are you saying that "&a" should mean "&(&a[0])"?  This doesn't make sense, as
>"&a[0]" is not an lvalue.

On a "prior art" note, VAX C allows objects like &3, even though 3 is not an
lvalue.  Because VMS is ruled by Fortran, most VMS services and library entries
expect everything passed by reference, even constants: as a convenience to
C programmers calling VMS routines, the expression &3 means "cons up an
anonymous int whose value is 3; value of the expression is the address of the
anonymous int."  So &a /could/ be given an analogous interpretation, one at
variance with your preference.

>address of an entire array entity (which differs from the address of the first
>element in exactly the same way that the address of a structure differs from
>the address of its first member), and this is exactly the problem that X3J11
>has fixed by legalizing "&a".

Um, no.  Given an object, s, of type "struct s", &s + 1 does NOT refer to the
second element in the struct.  Address arithmetic just doesn't "make sense"
with structures the same way that it does with arrays.

>
>Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

Steven Sargent (sarge@scam.berkeley.edu)

blarson@skat.usc.edu (Bob Larson) (12/12/87)

In article <5308@zen.berkeley.edu> sarge@scam.berkeley.edu (Steven Brian McKechnie Sargent) writes:
>On a "prior art" note, VAX C allows objects like &3, even though 3 is not an
>lvalue.

You mean Primos C isn't the only one with the "extention"?  Primos C
also does some bogus things with casts in procedure calls to "fortran"
(anything other than C must be declared fortran).  A code fragment:

fortran void tnou();		/* a routine from the standard library */
tnou((char [])"hello world", &(short)11);

The (char []) cast is needed.  Note you can also take the address of a
cast expression.
Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%fns1@ecla.usc.edu
			oberon!fns1!info-prime-request

chris@mimsy.UUCP (Chris Torek) (12/12/87)

>In article <555@ndsuvax.UUCP> ncbauers@ndsuvax.UUCP (Michael Bauers) writes:
>>The address of the array a[10] is just a.  The address of the first element
>>is also a (for single dimension arrays).

This is already confused.

>>The first element is *a.  But the address of the array's pointer

`The address of the array's pointer' is even more confused.

>>... should be &a.

In article <1442@houdi.UUCP> marty1@houdi.UUCP (M.BRILLIANT) writes:
>Huh?  I tried writing a C program on UNIX(tm ATT) that referenced &a,
>and got the message "warning: & before array or function: ignored."
>That says there's no such thing as &a.

Given the declaration

	int a[10];

the following is true:

	0. &a is currently illegal
	1. &a will be legal in the near future.
	2. In an expression, except as a target of sizeof, `a' and
	   `&a[0]' have identical meanings, namely a value of type
	   `pointer to int' that points to the first element of `a'
	   (a[0]).
	3. In an expression, `&a' will be a value of type
	   `pointer to (int [10])' that points to the array `a'.
	   Hence `*&a' will be a value of type `int [10]', which, in
	   all expression contexts except as a target of sizeof, is
	   immediately converted to a value of type `int *' (a.k.a.
	   `pointer to int') that points to the first element of
	   that array (here &a[0]).  Thus `*&a' will mean the same
	   thing as `a'.

Hence, in the near future, one will be able to write the following:

	f1()
	{
		int z[4][10];
		int (*p)[10];
		int i, j;

		p = g() ? &z[0] : &z[2];
		for (i = 0; i < 2; i++)
			for (j = 0; j < 10; j++)
				p[i][j] = (i + 1) * j;
		...
	}

At present, it is necessary to code this using casts (because &z[0]
elicits warnings or errors about & before array), or using code
like the following (with a cast version in comments):

	f2()
	{
		int z[4][10];
		/* int (*p)[10] */
		int *p;
		int i, j;

		/* p = (int (*)[10])(g() ? &z[0][0] : &z[2][0] */
		p = g() ? &z[0][0] : &z[2][0];
		for (i = 0; i < 2; i++)
			for (j = 0; j < 10; j++)
				/* p[i][j] = (i + 1) * j */
				p[i*10 + j] = (i + 1) * j;
		...
	}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

randy@umn-cs.cs.umn.edu (Randy Orrison) (12/13/87)

In article <5308@zen.berkeley.edu> sarge@scam.berkeley.edu (Steven Brian McKechnie Sargent) writes:
>In article <1949@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes:
>>address of an entire array entity (which differs from the address of the first
>>element in exactly the same way that the address of a structure differs from
>>the address of its first member), and this is exactly the problem that X3J11
>>has fixed by legalizing "&a".
>
>Um, no.  Given an object, s, of type "struct s", &s + 1 does NOT refer to the
>second element in the struct.  Address arithmetic just doesn't "make sense"
>with structures the same way that it does with arrays.

Um, yes.  Given an object, s, of type "struct snarf" or "array [n] of gonk",
&s + 1 is a pointer to the next object of the same type in memory.  Note
that in the case of arrays, &s + 1 is VERY different from the much more
common &s[0] + 1, which is the next element of the array. (There is nothing
that corresponds to this for structures, execpt &s[0]->firstelement).

In BOTH cases &s + 1 does NOT refer to the second element.   Nothing in that
expression talks about elements, and there's no way for the compiler to know
where to find the second element (whether s is a struct or array).


Now - the reason that you are confused:  The C that Karl and I are talking 
about is not the same C as you are used to.  This is ANSI C, not K&R, not
pcc, not H&R.

Now, I have a question:  this all makes sense to me if you have a variable of
type pointer to array { char (*s)[10] } but how does this apply when your
variable is an array itself { char s[10] }?  I suppose it makes sense...
is this right:

    With declarations (on the stack, contiguous in memory...)
	  char s[16];
	  char t[16];

	 Is it true that:  *(&s + 1) == t (assuming array comparisons)?

Arg.  Well, they may not be first class, but they're moving up in the world...

	-randy-- 
Randy Orrison, University of Minnesota School of Mathematics  |
UUCP:	{ihnp4, seismo!rutgers, sun}!umn-cs!randy	      |  (hello?)
ARPA:	randy@ux.acss.umn.edu		BITNET: randy@umnacca |
"I need a unit to sample and hold, but not the angry one: a new design."

marty1@houdi.UUCP (M.BRILLIANT) (12/14/87)

In article <9735@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> ... in the near future, one will be able to write the following:
> ...
> 		p = g() ? &z[0] : &z[2];
> ...
> At present, it is necessary to code this using casts (because &z[0]
> elicits warnings or errors about & before array), or using ....

Not so on the vax-785 with SV_R2 I'm logged in on now.  I can write
    ...
    char *a, b[14];
    ...
    a = &b[3];
    ...
without getting any complaints from the compiler.  It does what I want,
too: skips the beginning of the array.

Writing &b without an index in brackets still draws a warning from the
compiler that & before an array is ignored.  The storage location where
the array begins is known to the compiler by the name b, but since that
address is not accessible as data at run time, &b has no meaning.

Of course, writing &a draws no warnings, because a is a pointer, and
has both a value and a location where the value is stored.

M. B. Brilliant					Marty
AT&T-BL HO 3D-520	(201)-949-1858
Holmdel, NJ 07733	ihnp4!houdi!marty1

ncbauers@ndsuvax.UUCP (Michael Bauers) (12/15/87)

	To all who had to read the incorrect drivel I wrote...I apologise.
apparently &a is not the standard way to get at the adress of the pointer
to the array.  I had done &x (where x is an integer var.), before and it worked
fine, but &a (where a is an array) does not do the same thing according to
sources wiser than myself.  Would someone care to comment why &a does not
behave like &x does? 

  [-----------------------------------------------------------------------]
  [ Michael J. Bauers ( senior Computer Science at NDSU )                 ]
  [ Reply to:  NU100356@NDSUVM1 or ncbauers@ndsuvax.UUCP                  ]
  [ For God so loved the world that he gave his only son so that whoever  ]
  [   believes in him will not perish, but shall have eternal life.       ]
  [ Disclaimer:  Frankly I do not think NDSU cares what I think,          ]
  [              or even that I think at all.                             ]
  [-----------------------------------------------------------------------]

chris@mimsy.UUCP (Chris Torek) (12/15/87)

>In article <9735@mimsy.UUCP> I wrote:
>>... in the near future, one will be able to write the following:
[an important line deleted here]
>> 		p = g() ? &z[0] : &z[2];

In article <1445@houdi.UUCP> marty1@houdi.UUCP (M.BRILLIANT) writes:
>I can write
>    char *a, b[14];
>    a = &b[3];
>without getting any complaints from the compiler.

Yes, but you deleted my declaration for z:

	int z[4][10];

>Writing &b without an index in brackets still draws a warning from the
>compiler that & before an array is ignored.

Exactly: and it WILL NOT once your compiler is compliant with the
ANSI X3J11 standard.

>The storage location where the array begins is known to the compiler
>by the name b,

*WITH WHAT TYPE?*  Answer *THAT* and you may see what &b will mean.

>but since that address is not accessible as data at run time, &b has
>no meaning.

NO!  It has no meaning *NOW*; it *WILL* in the *FUTURE*!  AAAAAAARGH!

(There, I feel better now.)

Given the declaration `char b[14]', the value of &b will be the
same as the value of &b[10] with one important difference:  The
TYPE of &b[0] is `char *'; the TYPE of &b will be `char (*)[14]'.
[Aside: the exact representation of the two values may differ,
depending on, e.g., type tag bits.  This is irrelevant to the future
language definition.]

This is the key:  C is a typed language.  B is not; B has `words'.
C is; C has `pointer to char' and `pointer to pointer to char' and
`pointer to int' and . . . and each type is different and mutually
incompatible.  Two expressions with the same value but different
types are different.  The very quote above,

	`The storage location where the array begins...'

shows that you are thinking of C as an untyped language.  This is
wrong.  Every value has a type.  Given the declaration `int a[N};',
the difference between `&a[0]' and `&a' is the type of the expression.
Expressions are <type,value> pairs.  Leaving out either piece of
the pair gives you an improper expression: something that is not C.
Remember that: <type,value> pairs.  The difference between &a[0]
and &a is (will be) in the `type' half.

(Now *that* has *got* to be clear....)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

dik@cwi.nl (Dik T. Winter) (12/15/87)

Why is it that so many people cannot read and omit the saliant point when
answering?  To wit:

In article <1445@houdi.UUCP> marty1@houdi.UUCP (M.BRILLIANT) writes:
 > In article <9735@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
 > > ... in the near future, one will be able to write the following:
 > > ...
 > > 		p = g() ? &z[0] : &z[2];
 > > ...
 > > At present, it is necessary to code this using casts (because &z[0]
 > > elicits warnings or errors about & before array), or using ....
 > 
 > Not so on the vax-785 with SV_R2 I'm logged in on now.  I can write
 >     ...
 >     char *a, b[14];
 >     ...
 >     a = &b[3];
 >     ...
 > without getting any complaints from the compiler.  It does what I want,
 > too: skips the beginning of the array.
 > 
The declarations in the original article were:
 >		int z[4][10];
 >		int (*p)[10];
and that makes a lot of difference!
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

chris@mimsy.UUCP (Chris Torek) (12/15/87)

In article <9775@mimsy.UUCP> I wrote
>... the value of &b will be the same as the value of &b[10]

change `10' to `0'

>... Given the declaration `int a[N};',

change `}' to `]'

(Well, I was on an unfamiliar terminal.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/15/87)

In article <329@dlhpedg.co.uk> cl@.co.uk (Charles Lambert) writes:
>... the name of the array being a synonym for its address; ...

By oversimplifying, you got it wrong.  The name of an array is
converted IN SOME CONTEXTS to a pointer to the first element of
the array.  These contexts do not include as the operand of the
sizeof operator nor (as of ANSI C) as the operand of &.

As Chris Torek remarked, "address" should not be bandied about
when talking about C; C is a typed language, and its pointers
have definite types.  Understanding the &array issue requires
being careful about type distinctions.

throopw@xyzzy.UUCP (Wayne A. Throop) (12/18/87)

> References: <555@ndsuvax.UUCP>
> ncbauers@ndsuvax.UUCP (Michael Bauers)
> What they
> had meant to say I think was 'The adress of the array's pointer.'  

No, they really meant the address of the array.

> The article
> I was responding to was talking about taking the address of an array.  The
> address of the array a[10] is just a.

This is incorrect.  Detailed discussion below (which I hope hits a few
points not already covered by others).

> References: <126@citcom.UUCP> ... <3137@tut.cis.ohio-state.edu>
> lvc@tut.cis.ohio-state.edu (Lawrence V. Cipriani)
>>, marty1@houdi.UUCP (M.BRILLIANT)
>> That says there's no such thing as &a.
> This is like taking the address of a constant, say &0435241250,
> which of course is silly.

This is common folklore, that "arrays are constants" or "array names
represent constants".  This is true, but only for an unusual meaning of
the word "constant", involving "unchanging for a specific (but possibly
varying) lifetime".  "Constant" things are more normally thought of as
being unchanged at least as long as a process execution, normally
longer, and this is not true of arrays.

The address of the first element of a particular instance of an array is
a value that does not change for the lifetime of that instance of that
array.  But that's not the same thing as a "constant", at least, not as
most people think of constants.  Think of automatic arrays, for example.

By the way, the draft X3J11 standards document has changed the standard
way of talking about arrays.  In the terms as defined in the document,
it is incorrect to say that arrays are "constants", or that array names
evaluate to constants, or any of those common sayings.  In fact, arrays
are even lvalues as the term is defined in the standard.  (It turns out
that "lvalue" will no longer mean "may be assigned to".  Arrays are
examples of "non-modifyable lvalues".)

> Why do programmers want to do this?

It is most useful in dealing with arrays of arrays, or in dealing with
heaplike allocation of array objects.

> Do other
> languages let you do this?

Yes.  Pascal, Modula, PL/I (sort of), and more less-famous Algol
variants than you can shake a stick at.


> References: <329@dlhpedg.co.uk>
> cl@dlhpedg.co.uk (Charles Lambert)
> Any object, of any type (integer, structure, array, etc.), has an address.

Right.

> Usually, if it is an object that occupies several words of memory, it is the
> address at which it begins.

Wrong, at least if you are talking about how addresses are treated in C.
There is no such thing as "begins" and "ends" in terms of addresses of C
objects.  There is just the address of the object, period.  See my note
about the usage of the term "address" in the C language below, in
response to Doug Gwyn.

> In C,  the address of an array is the same as the address of its first
> element (array[0]).

No.  Because the address of the array and the address of the first
element *IN* *C* have different results when indirected or incremented.

> If you want to set up a pointer to the array, you
> get its address simply by naming it. Hence:
> 	pa = array;	/* pa now contains the address of "array" */

No.  Unless a type conversion not shown is implied by the assignment, pa
contains the address of the first element of array.

> Now this is a slight quirk in C - the name of the array being a synonym for
> its address;

This is not a quirk of C.  The name of an array is a synonym (but not
always) for the address of its first element, not for the whole array.
The two are distinct things.  K&R are very careful here, they do *NOT*
say that the name of an array is a synonym for that array's address.

> So we get back to the discussion from whence we came: why can't we be
> consistent and get the address of an array by
> 	pa = &array;	?
> To which the answer is:  you can, with some compilers.

But most often, compilers that allow this construct do it incorrectly,
and make it a synonym of 

        pa = array;

which is, of course, incorrect.  ANSI C compilers will get this correct.

> References: <6835@brl-smoke.ARPA>
> gwyn@brl-smoke.ARPA (Doug Gwyn )
> As Chris Torek remarked, "address" should not be bandied about
> when talking about C; C is a typed language, and its pointers
> have definite types.  Understanding the &array issue requires
> being careful about type distinctions.

Actually, K&R sort-of use "address" and "pointer" to refer to
indirectable-and-arithmetic-able rvalues and lvalues respectively.
Thus, I don't think it is wrong to talk about "addresses" in C.  But
you'd better remember that you aren't talking about address-of-anything.
In C, you are talking about address-of-something-in-particular.  (Yes,
I'm ignoring (void *) and function pointers for now.  So sue me.)

Remember, in C, "address" is a technical term, just as "pointer" is.
Or at least, that's the way I tend to use it.

> References: <15869@watmath.waterloo.edu>
> rbutterworth@watmath.waterloo.edu (Ray Butterworth)
> Isn't it amazing how many people are confused by such a simple
> concept as the address of an array?  If only K&R hadn't tried
> to "optimize" out this idea, I don't think there would be any
> of this confusion (at least no more than there is for the
> concept of the address of a structure).

Hear, hear!

--
"Technical term" is a technical term for a common word or phrase whose
meaning is, in some contexts, distorted beyond mortal comprehension.
                                --- Hal Peterson ihnp4!cray!hrp
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/19/87)

In article <569@ndsuvax.UUCP> ncbauers@ndsuvax.UUCP (Michael Bauers) writes:
>Would someone care to comment why &a does not behave like &x does? 

In ANSI C, it does!  In some older C compilers, &a was illegal, and in
others &a was treated like plain a (i.e. as &a[0]).

lvc@tut.cis.ohio-state.edu (Lawrence V. Cipriani) (12/21/87)

After think about array address a bit, I see how silly I
have been in thinking they were silly.  Most of this is
obvious, but here it is anyway.  Maybe someone else will
benefit from this too.

Here is what I hope is a correct interpretation of array
address.  This is mostly borrowed from other postings.
Thanks to Torek, Throop, Butterworth, Gwyn, and Heuer,
etc.

1) Every object has an address.  Arrays are objects, so
   they must have addresses.

2) The name of an array is a synonym for the address of
   the first element of the array.  This is only a CONVENIENCE
   so you can write:
	for (p = name; p < &name[NTHINGS]; p++);
   instead of having to write:
	for (p = &name[0]; p < &name[NTHINGS]; p++);

3) The name of an array is NOT a synonym for the address of
   the array.

4) When you indirect a pointer to an array, you get an ARRAY.

5) When you increment (decrement) a pointer to an array, you
   point to the "next" ("previous") array.

6) Given:
	int ident[4];

   The value of &ident might NUMERICALLY happen to equal
   &ident[0] but they are different because they have different
   TYPES.  &ident is of type (int *)[4], and &ident[0] is of
   type (int *).

7) Given:
	int ident[2][4], (*pai)[4] = &ident[0];

	pai++ would be equal to &ident[1]

	pai = &ident[3];
	pai-- would be equal to &ident[2];

8) ANSI C will allow:
	int ident[2][4], (*pai)[4] = &ident[0];
   but not:
	int ident[2][4], (*pai)[5] = &ident[0];

Now, a question on ANSI C. Will you be able to do this:

	int ident[2][4];
	int (*pai)[4] = &ident[0];
	int (*pbi)[4] = &ident[1];

	code that manipulates ident[0]

	*pbi = *pai;

Thanks for all the info.
-- 
	Larry Cipriani AT&T Network Systems at
	cbosgd!osu-cis!tut!lvc Ohio State University

domo@riddle.UUCP (Dominic Dunlop) (12/23/87)

In article <9735@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
[Quotes from other postings deleted]
>Given the declaration
>
>	int a[10];
>
>the following is true:
>
>	0. &a is currently illegal
>	1. &a will be legal in the near future.
[Further points and examples deleted]

Well, I didn't agree with point 1.  Looking at the November 9 draft of
the proposed ANSI standard, I found that it says concisely in 3.3.3.2
-- Address and Indirection Operators:

	The operand of the unary & operator shall either be a function
	designator or an lvalue that designates an object that is not a
	bit-field and is not declared with the register storage class
	specifier.

This confirmed my prejudice, namely that & applied to an object of array 
type is an error.  But then I looked in 3.2.2.1 -- Lvalues and function
designators:

	An lvalue is an expression ... that designates an object...
	A modifiable lvalue is an lvalue that does not have array type...

	Except when it is the operand of the sizeof operator or the unary &
	operator, or is a string literal used to initialize an array of
	characters, an lvalue which has type ``array of type'' is converted
	to an expression that has type ``pointer to type'' that points to
	the initial member of the array object and is not an lvalue.

To summarize, an array can now be an lvalue, albeit not a modifiable one,
and consequently, the & operator can be applied to it.  The draft does not
explicitly say what happens when the operator is so applied.  I assume that
the address of the whole array is delivered, and that the type of the
result is ``pointer to array of ...''  What on earth are the consequences
of this, and why was it done?  Who needs a ``pointer to array of ...''

Enlightenment, please...
-- 
Dominic Dunlop
domo@sphinx.co.uk  domo@riddle.uucp

throopw@xyzzy.UUCP (Wayne A. Throop) (12/24/87)

> lvc@tut.cis.ohio-state.edu (Lawrence V. Cipriani)
> Summary: do I have it right now?

Yep.  But I can't resist clarifying one little nit.
Something in my upbringing, I think.

> 2) The name of an array is a synonym for the address of
>    the first element of the array.  This is only a CONVENIENCE
>    so you can write:
> 	for (p = name; p < &name[NTHINGS]; p++);
>    instead of having to write:
> 	for (p = &name[0]; p < &name[NTHINGS]; p++);

This is *right*, sort of, but I wouldn't put it this way, and putting it
this way gives me an itchy sensation I just have to scratch.

The way I think of it is not that an array name is a synonym for the
address of the first element of the array, but that any array object,
when encountered in an expression, is converted to the address of the
first element in the array (except when object of sizeof or '&'
operators).  Note: "is converted", not "is a synonym".  This way of
thinking about it handles arrays of arrays nicely, while the alternate
requires one to consider aa[N] to be the "name" of an array, which is
not quite right.  A small nit, perhaps, but I think it helps to think of
it this way.

Further, this isn't so much a convenience as it is a direct fallout of
the definition of the subscripting/address-arithmetic equivalence in C.
Personally, I would have done it just the way Larry describes above, and
define pointer arithmetic in terms of array subscripting.  But K&R in
their wisdom did the reverse: subscripting is defined in terms of
pointer arithmetic.  This means that an array object, when used in a
subscripting expression, *MUST* be converted to the address of the first
element of the array for the subscript operation to work at all.  K&R
just extended this to become the default situation: array objects in
most expressions are converted as they are in subscript expressions.
Again, a small nit, but [etc, etc].

--
There are some forms of insanity which, driven to an ultimate
expression, can become new models of sanity.
                        --- Bureau of Sabotage {Frank Herbert}
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw