Velocity Reviews > Pointer Declaration/Array definition

# Pointer Declaration/Array definition

Chris Torek
Guest
Posts: n/a

 08-22-2004
In article <news:cgaf5k\$p5e\$(E-Mail Removed)> <(E-Mail Removed)> wrote:
>Ok, here is what I want to know: What exactly happens when
>p[i] is called, as far accessing and dereferncing that makes
>the code wrong (yes, I know it should not work, I just want
>to know why).

In some cases, a picture is worth a thousand words. (Be sure to
view this in a fixed-width font.)

void f(void) {
char a[6] = { '1', '2', '3' };
char *p;
...
}

+-----------------------------------+
| '1' | '2' | '3' | 0 | 0 | 0 |
+-----------------------------------+

+-------------------+ /------------->
+-------------------+

The larger box represents "a", which is made up of six bytes (each
char in C is a "C byte", always). The six bytes have known values
because we initialized "a".

The smaller box represents p, the pointer. We did not initialize
it, so (assuming these are inside a function, as in the example
code) it is full of trash. If viewed as a pointer, the result is
unpredictable -- in this case I have drawn it as a "wild pointer"
pointing off into the weeds somewhere.

Now, if we set p to point to the first element of "a":

p = &a[0];

we get a new picture:

+-----------------------------------+
| '1' | '2' | '3' | 0 | 0 | 0 |
+-----------------------------------+
^
|
+--------------------+
|
+-------------------+ |
+-------------------+

Now p contains an arrow pointing to &a[0].

When you write a[i], the compiler says to itself: "aha, `a', that
is declared as an array, and you want to do something with the
`value' of `a' -- index it like an array, in this case -- so I will
construct a pointer pointing to &a[0] and use that."

This special rule about arrays is a quirk of C. Many other languages
are very different in their treatment of arrays. There is no
fundamental reason the C language *has* to work this way; it just
does. That means that you simply have to memorize this rule. It
is a thing you have to know about C that has no reason other than
"the guy who wrote the language decided to do it that way" -- rather
like the syntax for declarations.

On the other hand, when you write p[i], the compiler takes the
pointer value p already has -- here, pointing to &a[0] -- and
follows the arrow and then "moves right" according to the number
in "i". Moreover, if you have the variable "p", you can set it
to point to some place other than &a[0]:

p = &a[2];

makes p point to the '3', and p[1] is the first 0 (or '\0' -- same
thing) byte, while p[-2] and p[-1] now exist, naming the '1' and
'2' in a[0] and a[1] respectively. This is because the compiler
generates code that follows the arrow and then "moves right" as
requested, and you have already moved right -- which lets you move
left again, if you want to.

The difference between using a pointer ("p") and using the array
name ("a"), then, is that when you use the array name, the compiler
has to take an extra step to *construct* the pointer it needs, just
so that it can then follow the pointer. Curiously, this extra work
*can* (not necessarily "does", just "can") result in faster machine
code. The reason is that the compiler is allowed to know a lot
more about the pointer it constructed here, *because it constructed
it*. It is not some unknown pointer taken in off the street, with
a mysterious and shady background. The constructed pointer has a
solid pedigree. Of course, given a local variable like "p", a
smart compiler can probably look around and figure out whether "p"
has a similar pedigree -- so on *good* compilers, there tends to
be little if any performance difference. On not-so-good compilers,
it is hard to tell which will be faster -- the array, because the
compiler knows about the pointer it makes, or the pointer, because
the compiler does not have to do the extra "make a pointer" step.
Or perhaps neither will be faster there, either.

The moral of the "performance story" above, as it were, is: use
whichever one is clearer to the human programmer. On a good compiler
it will make no real difference, and on a bad one, you cannot predict
what kind of difference it will make.

<http://web.torek.net/torek/c/pa.html>.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
Reading email is like searching for food in the garbage, thanks to spammers.

Ivan Vecerina
Guest
Posts: n/a

 08-22-2004
<(E-Mail Removed)> wrote in message
news:cgapcd\$t35\$(E-Mail Removed)...
| Ivan Vecerina <(E-Mail Removed)> wrote:
| > This "implicit conversion" is performed by the compiler, when
| > it knows that an array is being used as if it were a pointer.
| > But the generated code and memory layout is very different.
....
| Thanks. Referring to some other posts, does this "implicit
| conversion" also known as "decaying convention?"

Some like to say that arrays "decay" into pointers,
which illustrates the fact that the conversion is
not (easily) reversed. But I've also seen it use
to designate the fact that function parameters declared
as having an array type are actually treated as pointers.
E.g.:
int f( char param[16] );
is interpreted by the compiler as:
int f( char *param );

hth
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

Dan Pop
Guest
Posts: n/a

 08-23-2004
In <cg9amc\$ogh\$(E-Mail Removed)> http://www.velocityreviews.com/forums/(E-Mail Removed) writes:

>Why does this declaration give undefined result:
>
>file1: extern char * p;
>file2: char p[10];

Why did you expect anything else? It's the same as:

file1: extern double c;
file2: char c;

All declarations of the same object must match its definition.

If you think that there is anything special about pointers and arrays
in this context, read the FAQ.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)