Address of address

G

Guest

If I have an array of int:

int array[8];

I suppose the correct way to clear it using memset() would be:
memset(array, 0, 8 * sizeof(int));

However, I've seen the following in a piece of code:
memset(&array, 0, 8 * sizeof(int));

What does (or shall) the compiler do in this case? Is the behaviour defined?

/Krister
 
R

Richard Heathfield

(e-mail address removed) said:
If I have an array of int:

int array[8];

I suppose the correct way to clear it using memset() would be:
memset(array, 0, 8 * sizeof(int));

You can initialise it like this:

int array[8] = {0};

If you need to zero it, then memset is okay provided the array is composed
entirely of integers. If you have floats or pointers in there, maybe in
structs, then memset isn't guaranteed to give them zero values.

Just use: memset(array, 0, sizeof array);

Curiously, this works too:

memset(&array, 0, sizeof array);

Both are correct, for slightly different reasons. (That doesn't mean that
array and &array are synonymous; they aren't.)

Some will prefer the latter choice on idiomatic grounds. And some will
prefer the former - on idiomatic grounds! :)

However, I've seen the following in a piece of code:
memset(&array, 0, 8 * sizeof(int));

Eesh. Someone's trying hard to make life difficult for themselves.
What does (or shall) the compiler do in this case? Is the behaviour
defined?

Provided it really is an array of int and really does have 8 members, yeah,
that works fine. It's just rather noisy, that's all.
 
A

Ancient_Hacker

If I have an array of int:

int array[8];

I suppose the correct way to clear it using memset() would be:
memset(array, 0, 8 * sizeof(int));

yep, that's swell, until somebody changes the type of "array". Or the
number of elements in it.

Maybe you can think of a better wording of that statement?

However, I've seen the following in a piece of code:
memset(&array, 0, 8 * sizeof(int));

What does (or shall) the compiler do in this case? Is the behaviour defined?

The general rule is, the name of an array *is* the address of the
array. This funny shortcut exists because there are NO operations in C
that can take place with the VALUE of a whole array, so an array name
cannot mean "get me the value", so it defaults to "gimme the address".

So you never have to put an ampersand in front of an array name. Many
compilers put out an informative warning if you do so.

This doesnt apply if the array is subscripted! For example, array[1]
is manipulable by C's code generator, so array[1] means the VALUE of
that element. So if you need to pass the address of that element, you
do need an ampersand.
 
R

Richard Heathfield

Ancient_Hacker said:

So you never have to put an ampersand in front of an array name.

You do if you want the address of the array.

Many
compilers put out an informative warning if you do so.

This doesnt apply if the array is subscripted! For example, array[1]
is manipulable by C's code generator, so array[1] means the VALUE of
that element. So if you need to pass the address of that element, you
do need an ampersand.

And just maybe that element is itself an array, in which case you are
contradicting yourself.
 
A

Ancient_Hacker

Richard said:
Ancient_Hacker said:



You do if you want the address of the array.\

Could you shed some light in this area? What do you get with just the
array name that is in any way different from ampersand followed by the
array name?
Inquiring minds want to know.

Many
compilers put out an informative warning if you do so.

This doesnt apply if the array is subscripted! For example, array[1]
is manipulable by C's code generator, so array[1] means the VALUE of
that element. So if you need to pass the address of that element, you
do need an ampersand.
And just maybe that element is itself an array, in which case you are
contradicting yourself.

No contradiction, I think, I didnt say "pass the address value stored
in that element".
 
R

Richard Heathfield

Ancient_Hacker said:
Could you shed some light in this area? What do you get with just the
array name that is in any way different from ampersand followed by the
array name?

A different type.

Let's take a nice simple example:

#include "t.h" /* write your own :) */

T myarray[N] = {0}; /* 1 */

T *p = myarray; /* 2 */

In line 2, the expression myarray is exactly equivalent to &myarray[0],
and yields a value that has type T*. It's the address of the first element
of the array.

size_t arrsize = sizeof myarray; /* 3 */

In line 3, myarray is the operand of sizeof, and sizeof doesn't evaluate its
operands, so myarray refers to the array itself. Thus, arrsize is equal to
N * sizeof(T).

size_t arrptrsize = sizeof &myarray; /* 4 */

In line 4, myarray is the operand of the address operator, which again does
not evaluate its operand. The address thus given has type T (*)[N], and so
the whole expression &myarray yields an expression of that type.
Consequently, that is the expression type that becomes the operand of
sizeof. On a typical modern desktop system, arrptrsize will now hold the
value 4, rather than the value N * sizeof(T).
 
C

Chris Dollin

Ancient_Hacker said:
Could you shed some light in this area? What do you get with just the
array name that is in any way different from ampersand followed by the
array name?

The array name decays (in value context) to the address of its first
element. This is not the same as the address of the array: they have
different types.

#include <stdio.h>

void accept( int *foo ) {}

int main()
{
int foo[2] = {0};
accept( foo );
accept( &foo );
return 0;
}

gcc -ansi -pedantic it.c
it.c: In function 'main':
it.c:9: warning: passing argument 1 of 'accept' from incompatible pointer type

Line 9 is the second call to `accept`.
 
F

Frederick Gotham

posted:
If I have an array of int:

int array[8];

I suppose the correct way to clear it using memset() would be:
memset(array, 0, 8 * sizeof(int));

However, I've seen the following in a piece of code:
memset(&array, 0, 8 * sizeof(int));


The type of the following expression:

array

is int[8]. When used in a context where a pointer is required, it decays to
a pointer to the first element of the array -- thus yielding an expression
of the type int* (which refers to &array[0]).

The type of the following expression:

&array

is int(*)[8], i.e. it is a pointer to an array consisting of eight
elements.
 
F

Frederick Gotham

Ancient_Hacker posted:
So you never have to put an ampersand in front of an array name. Many
compilers put out an informative warning if you do so.

With regard to a card game (such as poker), let's write a function which
takes as an argument the quantity of cards in a hand which are of a
particular suite; here's one way of doing it:

void AnalyseHand(unsigned const (*const quant_suite)[4])
{

}

int main(void)
{
unsigned const suite[4] = {5,3,7,2};
AnalyseHand(&suite);
}

There's plenty of good uses for a pointer to an array.
 
K

Keith Thompson

Ancient_Hacker said:
The general rule is, the name of an array *is* the address of the
array. This funny shortcut exists because there are NO operations in C
that can take place with the VALUE of a whole array, so an array name
cannot mean "get me the value", so it defaults to "gimme the address".

Only if by "general" you mean "incomplete".

The general rule is this (C99 6.3.2.1p3):

Except when it is the operand of the sizeof operator or the unary
& operator, or is a string literal used to initialize an array, an
expression that has type "array of _type_" is converted to an
expression with type "pointer to _type_" that points to the
initial element of the array object and is not an lvalue. If the
array object has register storage class, the behavior is
undefined.
So you never have to put an ampersand in front of an array name. Many
compilers put out an informative warning if you do so.

&array is a perfectly legitimate expression; it yields the address of
the array, which is distict from the address of its first element.
They have the "same value" in some sense, but they're of different
types.

For example, given "int array[10];", the expression "array + 1" is of
type int* and yields the address of the second element of array, and
the expression "&array + 1" is of type int(*)[10] (pointer to array of
10 ints), and yields a pointer just past the end of the object.

Most arrays are accessed via pointers to their elements, so taking the
address of a full array is relatively rare -- but it is meaningful,
and quite distinct from taking the address of an array element.
This doesnt apply if the array is subscripted! For example, array[1]
is manipulable by C's code generator, so array[1] means the VALUE of
that element. So if you need to pass the address of that element, you
do need an ampersand.

On the contrary, the actual rule does apply to subscript operations.
The subscript operator, x[y], is by definition equivalent to *(x + y),
where one operand is a pointer and the other is an integer. In the
expression "array[5]", the expression "array" is implicitly converted
to a pointer. This is just the normal conversion that usually happens
to array expressions; it has nothing to do with the indexing
operation.

Arrays are not pointers. Pointers are not arrays. It's important to
keep this in mind, in spite of the language's best efforts to make you
think otherwise.

See section 6 of the comp.lang.c FAQ, <http://www.c-faq.com/>, "Arrays
and pointers".
 
P

pete

Ancient_Hacker wrote:
So you never have to put an ampersand in front of an array name. Many
compilers put out an informative warning if you do so.

This doesnt apply if the array is subscripted! For example, array[1]
is manipulable by C's code generator, so array[1] means the VALUE of
that element.
So if you need to pass the address of that element,
you do

You don't.
need an ampersand.

The address of array[1] is (array + 1).
 

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,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top