Why do so few people know the difference between arrays and pointers.

D

Dan Pop

Just a question/observation out of frustration.

I read in depth the book by Peter Van Der Linden entitled
"Expert C Programming" (Deep C Secrets). In particular the
chapters entitled:
4: The Shocking Truth: C Arrays and Pointers Are NOT the Same!
9: More about Arrays
10: More about Pointers

What blows me out of the water is the fact that 'every' programmer
comming out of college that I've interviewed thinks that pointers
and arrays are the same thing.

They go so far as to tell me that, in the following code, 'arr' is
a pointer to an array of integers. Or they tell me that 'arr' is a
pointer to an 'int'. When this is not the case at all.

The root of the problem is the fact that most C books don't explain
"the rule" right. This is one of the few places where the text of the
C standard itself is more clear than the usual tutorial book. Even K&R2
contains statements like:

Since the name of an array is a synonym for the location of the
initial element...

that are much more misleading than helpful. After reading K&R1, I
conceptualised arrays as constant pointers (or pointer constants) to
an unnamed storage area, rather than the storage area itself, whose
name gets automatically converted to a pointer to its first element
in most contexts. This explained why you cannot assign anything to
an array, but didn't scale well conceptually to arrays of arrays.
It was the c.l.c FAQ that finally clarified the issue for me.

Dan
 
M

Mike Wahler

JV said:
What's 'wrong' with using multi-dimensional arrays,
and what will come to me if I use one?

I won't ask what you consider a 'fancy' declaration.

-Mike
I think what confuses people learning C is that if you declare two arrays:

int a[10]
int b[10][10]

then a[0] is integer and b[0] is a pointer to integer.

No. b[0] is not a pointer. It's an array, of type 'int[10]'

A pointer is not an array.
An array is not a pointer.

I've said this a zillion times here, I suppose I'll
never be able to stop. :)

-Mike
 
M

Mike Wahler

Vijay Kumar R Zanvar said:
... and when a character string literal is used to initialize an array.

In that case, the array's name is not being used an an expression.

-Mike
 
M

Mike Wahler

*a said:
hi all; i'm a self-taught C-hobbyst; i want to sing k&r's praises: their
book was somewhat hard for me, i proceeded slowly, sometimes at the "speed"
of few pages/week, but it's impossible to confuse pointer with arrays then;

the problem is C needs a non-superficial study

I think this remark hits the mark exactly.

It seems the concise syntax and 'smalless' of C's language
proper leads many to believe it's 'simple', thus they often
don't see the need for deeper study, practice, and experimentation.
But of course C is not really very 'simple' at all. It is indeed
powerful, though.

$.02,
-Mike
 
M

Malcolm

Mike Wahler said:
void bar(void)
{
int arr[100];

foo(arr);
}

calls foo with a pointer to an array of integers.

Wrong. Calls 'foo()' with a pointer to an 'int'.
(type 'int*'). Pointer-to-int and pointer-to-array-of-ints
are not the same type.

int *p; /* pointer to int */
int (*pa)[100]; /* pointer to array of 100 ints */
That's the difference between C usage and English usage. C doesn't
distinguish between a pointer to an area of memory containing a single
integer, or an area containing an array of integers. It is correct to say
that bar receives a pointer to 100 integers, and since they are in an array,
it is also correct to say that it receives a pointer to an array of 100
integers. However it is also correct to say that this is false.
What's 'wrong' with using multi-dimensional arrays,
and what will come to me if I use one?
The syntax is horrible and they have few real applications (most 2d arrays
have at least one variable dimension). Your code will be hard to read and
the use of multi-dimension constructs will suggest to the reader that you
don't have much experience with C. Consequently when bugs appear in your
code, as happens to us all from time to time, it will be re-written from
scratch instead of mended. This will cause your employers to question the
value of your continued employment, and in a tight market because of
outsourcing to India you will not be able to find another job, and if you
have few skills outside It you will be forced to take a position at Burger
King where the other staff will laugh at you for being too middle class, so
you will leave and hit the streets, and end your days as a tramp or beggar.
 
A

Arthur J. O'Dwyer

That's the difference between C usage and English usage. C doesn't
distinguish between a pointer to an area of memory containing a single
integer, or an area containing an array of integers. It is correct to say
that bar receives a pointer to 100 integers, and since they are in an array,
it is also correct to say that it receives a pointer to an array of 100
integers. However it is also correct to say that this is false.

The simplest way out of this dilemma, in the context of the C
programming language (which is always the context in this newsgroup),
is to reserve the use of the word "pointer" for the C language's
pointers, and to use the English term "address" for what you seem
to be calling a "pointer." Thus:

'main' calls the function 'foo' with an argument which is a pointer
to an 'int'.
'main' calls 'foo' with a pointer to 'int'.
'main' calls 'foo' with a pointer which holds the address of the
array 'bar'.
'bar' is an array[100] of 'int'.
The address of 'bar' is also the address of the first element of 'bar'.
The expression 'bar' decays to a pointer to the first element of 'bar'.
All pointer values have associated types.
Addresses do not have types.
The unary '&' operator yields a pointer to the operand object.
The unary '&' operator yields the address of the operand object
as a value of type "pointer to quux."

All clear, no?

-Arthur
 
D

Dan Pop

In said:
JV said:
I think what confuses people learning C is that if you declare two arrays:
int a[10]
int b[10][10]
then a[0] is integer and b[0] is a pointer to integer.

It would confuse them, yes. Fortunately it's not true. b[0] is an
array of ten integers.

Which *immediately* decays into ... unless used as the operand of the
sizeof or unary & operators. This is the confusing bit.

Dan
 
M

Mike Wahler

Malcolm said:
Mike Wahler said:
void bar(void)
{
int arr[100];

foo(arr);
}

calls foo with a pointer to an array of integers.

Wrong. Calls 'foo()' with a pointer to an 'int'.
(type 'int*'). Pointer-to-int and pointer-to-array-of-ints
are not the same type.

int *p; /* pointer to int */
int (*pa)[100]; /* pointer to array of 100 ints */
That's the difference between C usage and English usage.

Lacking explicit qualification to the contrary,
C meanings take precedence here.
C doesn't
distinguish between a pointer to an area of memory containing a single
integer, or an area containing an array of integers.

Actually, yes it does. The types are not the same (nor need
their sizes be the same) Also, the types yielded by dereferencing
those two different type pointers are not the same, nor are their
sizes -- except in the case of a pointer to an array of one element
-- that is, their sizes would be the same, but their types still
would not).
It is correct to say
that bar receives a pointer to 100 integers,

No it's not. The name of an array, when passed to a function,
decays to a pointer to its first element. The type passed
is 'pointer-to-array-element-type'.
and since they are in an array,

That doesn't matter.
it is also correct to say that it receives a pointer to an array of 100
integers.

No, it is not correct. Again:

Pointer to array of 100 ints:

int (*pa)[100];

Pointer to int:

int *p;

Those two types are *not* the same. If they were, then this
would be valid:

void foo(int (*arg)[100])
{
}

void bar(void)
{
int arr[100];
foo(arr);
}

... but it doesn't.

However it is also correct to say that this is false.
Huh?

The syntax is horrible

A matter of opinion. I have no trouble with the syntax.
and they have few real applications (most 2d arrays
have at least one variable dimension).

Subjective assesment. You're limiting your view to
only those applications you can conceive. Your phrase
'most 2d arrays' is without context, so hasn't any
useful meaning..
Your code will be hard to read

Subjective opinion again.
and
the use of multi-dimension constructs will suggest to the reader that you
don't have much experience with C.

That made me laugh out loud.
Consequently when bugs appear in your
code,

So you're saying that simply by using a 2d array has
the effect of creating bugs? Oh, please.
as happens to us all from time to time,

Yes, being human, everyone makes mistakes occasionally
(or perhaps even frequently). But the use of a particular
(valid) construct is not a direct cause. What create bugs
are carelessness and/or insufficient knowledge.
it will be re-written from
scratch instead of mended.

Depending upon how 'broken' a program is, sometimes
a rewrite is indeed the superior choice. This has
indeed been the case a few times in my experience
(both with my own code, and that of others). But
the cause was never the use of a valid language
construct. Sometimes I'll see that a particular
construct was not the best solution, but that's
a case of poor design, not 'bugs'.
This will cause your employers to question the
value of your continued employment,

Any employer/client I might wish to work with will
judge my value by that of what I produce. The value
of those products is determined by a consumer market,
not anyone's opinions about whether I understand C or not.
and in a tight market because of
outsourcing to India you will not be able to find another job,

Being an unabashed capitalist, I gladly welcome competition
from anyone, anywhere. I don't blame others for any problems
I might have, I take responsibility for solving them.
and if you
have few skills outside It you will be forced to take a position at Burger
King where the other staff will laugh at you for being too middle class,
so
you will leave and hit the streets, and end your days as a tramp or
beggar.

There is nothing dishonorable about working in the food service
industry, or any other value-producing profession. Nor do I allow
derision of others to dictate my actions.

You sir, are a snob.

-Mike
 
E

E. Robert Tisdale

Dan said:
Joona I Palaste writes:

JV scribbled the following:
Mike Wahler wrote:

What's 'wrong' with using multi-dimensional arrays,
and what will come to me if I use one?

I won't ask what you consider a 'fancy' declaration.

I think what confuses people learning C is that if you declare two arrays:
int a[10]
int b[10][10]
then a[0] is integer and b[0] is a pointer to integer.

It would confuse them, yes. Fortunately it's not true.
b[0] is an array of ten integers.
> cat main.c
#include <stdio.h>

int main(int argc, char* argv[]) {
int b[10][10];
printf("%u = sizeof(b[4])\n", sizeof(b[4]));
return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
40 = sizeof(b[4])
Which *immediately* decays into ...
unless used as the operand of the sizeof or unary & operators.
This is the confusing bit.

I know what you mean
but "decay" or "decays into" is inaccurate and confusing.
It seems to imply some sort of *spontaneous* reaction
which certainly does *not* occur in properly functioning C programs.
The correct way to think of this is an *implicit conversion*
from a reference to an array to a pointer to it's first element.
 
J

Joona I Palaste

Dan Pop said:
In said:
JV said:
What's 'wrong' with using multi-dimensional arrays,
and what will come to me if I use one?

I won't ask what you consider a 'fancy' declaration.

I think what confuses people learning C is that if you declare two arrays:
int a[10]
int b[10][10]
then a[0] is integer and b[0] is a pointer to integer.

It would confuse them, yes. Fortunately it's not true. b[0] is an
array of ten integers.
Which *immediately* decays into ... unless used as the operand of the
sizeof or unary & operators. This is the confusing bit.

Yes, I agree. It is the same situation with a one-dimensional array, so
arrays of arrays don't have any magical properties.
One way to understand the difference is to think of the raw bytes
comprising the objects. An array is simply several values (ints in
this case) put immediately after each other. Nothing more. There are
no array-specific bits or bytes involved.
A pointer, OTOH, is a value that constitutes the address of another
value. This address value is stored in the object, but the actual
values (ints in this case) it points to can be stored pretty much
anywhere. A pointer definitely has extra pointer-specific bits or
bytes involved - otherwise it wouldn't know where to point.
Arrays can't coincide or overlap each other, any more than normal
values (ints in this case) can. However, several pointers can point
at the same place, or inside each other's defined pointing range.
As usual, I may have been inaccurate at some points. Corrections are
welcome.
 
M

Malcolm

Mike Wahler said:
Actually, yes it does. The types are not the same (nor need
their sizes be the same) Also, the types yielded by dereferencing
those two different type pointers are not the same, nor are their
sizes -- except in the case of a pointer to an array of one element
-- that is, their sizes would be the same, but their types still
would not).
Say we want to write a function to return a cursor position. Any C
programmer would write this

void getcursorxy(int *x, int *y)
{
*x = xposition;
*y = yposition;
}

Now imagine a function to calculate a correlation coefficient. Again any C
programmer would write

double correlation(int *xvals, int *yvals, int N)
Pointer to array of 100 ints:

int (*pa)[100];

Pointer to int:

int *p;

Those two types are *not* the same.
No, but int *p is not constrained to pointing at a memory object containing
only one integer.
 
B

Barry Schwarz

Mike Wahler said:
Actually, yes it does. The types are not the same (nor need
their sizes be the same) Also, the types yielded by dereferencing
those two different type pointers are not the same, nor are their
sizes -- except in the case of a pointer to an array of one element
-- that is, their sizes would be the same, but their types still
would not).
Say we want to write a function to return a cursor position. Any C
programmer would write this

void getcursorxy(int *x, int *y)
{
*x = xposition;
*y = yposition;
}

Now imagine a function to calculate a correlation coefficient. Again any C
programmer would write

double correlation(int *xvals, int *yvals, int N)
Pointer to array of 100 ints:

int (*pa)[100];

Pointer to int:

int *p;

Those two types are *not* the same.
No, but int *p is not constrained to pointing at a memory object containing
only one integer.

int *p, when properly initialized, points to a single int by
definition. The fact that p+1 may also be the address of an int is a
function of the program design and not an inherent property of p.


<<Remove the del for email>>
 
R

Richard Bos

Malcolm said:
Say we want to write a function to return a cursor position. Any C
programmer would write this

void getcursorxy(int *x, int *y)
{
*x = xposition;
*y = yposition;
}

Erm... I'd almost certainly not write it like that. Even if the global
values would be unavoidable (and I would try to avoid them), I'd be more
likely to write

struct coords getcursorxy()
{
struct coords t;

t.x=global_x;
t.y=global_y;

return t;
}
Now imagine a function to calculate a correlation coefficient. Again any C
programmer would write

double correlation(int *xvals, int *yvals, int N)

Yes, in this case I probably would.

I fail to see the problem, btw. I see your point (that any given int
pointer can point at memory the size of one int, two ints, or a
gazillion ints); but I do not see why this is a problem to you. For any
given function, a pointer can point at
- one object (possibly part of a larger memory area) - in this case, you
use *ptr, and the rest of the memory, if any, is irrelevant;
- a number of objects, which can be as low as one and as high as the
sky, or possibly even zero - in which case, you need to pass in the
number of elements in any case, no matter whether there happens to be
just one object in this single call or not.

Someone who does not understand this will have problems programming in
C, yes. So what? Let him "program" in HTML; should suit him fine.
Pointer to array of 100 ints:

int (*pa)[100];

Pointer to int:

int *p;

Those two types are *not* the same.
No, but int *p is not constrained to pointing at a memory object containing
only one integer.

Again: so what? If you expect one int, other ints which happen to be
positioned next to your int in memory are irrelevant.
If I send a letter to you, should I care whether you live in a detached
house or in a flat? Of course not - as long as I have your correct
address, the letter will arrive fine.

Richard
 
J

JV

Joona I Palaste said:
JV said:
I think what confuses people learning C is that if you declare two
arrays:
int a[10]
int b[10][10]
then a[0] is integer and b[0] is a pointer to integer.

It would confuse them, yes. Fortunately it's not true. b[0] is an
array of ten integers.

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"The obvious mathematical breakthrough would be development of an easy way to
factor large prime numbers."
- Bill Gates

Hmm, it seems that I still have to work on how to present my ideas
clearly:). So lets say that you can use notation b[0] as a pointer to
integer and you can assign a[0] to integer variable. So you can't tell if
you see expression like a what it actually is without knowing the
declaration. And I KNOW that arrays are not pointers and still I managed to
get it wrong in my previous post ...
-Jyrki
 
C

CBFalconer

JV said:
Joona I Palaste said:
JV said:
What's 'wrong' with using multi-dimensional arrays,
and what will come to me if I use one?

I won't ask what you consider a 'fancy' declaration.

I think what confuses people learning C is that if you declare
two arrays:

int a[10]
int b[10][10]

then a[0] is integer and b[0] is a pointer to integer.

It would confuse them, yes. Fortunately it's not true. b[0] is
an array of ten integers.

Hmm, it seems that I still have to work on how to present my
ideas clearly:). So lets say that you can use notation b[0] as
a pointer to integer and you can assign a[0] to integer
variable. So you can't tell if you see expression like a what
it actually is without knowing the declaration. And I KNOW that
arrays are not pointers and still I managed to get it wrong in
my previous post ...


You also need to work on your snipping technique and delineation
of your sig (with "-- "). This has minimal snippage, but compare
it to your actual article.
 
M

Mike Wahler

Malcolm said:
Mike Wahler said:
Actually, yes it does. The types are not the same (nor need
their sizes be the same) Also, the types yielded by dereferencing
those two different type pointers are not the same, nor are their
sizes -- except in the case of a pointer to an array of one element
-- that is, their sizes would be the same, but their types still
would not).
Say we want to write a function to return a cursor position. Any C
programmer would write this

void getcursorxy(int *x, int *y)
{
*x = xposition;
*y = yposition;
}

Now imagine a function to calculate a correlation coefficient. Again any C
programmer would write

double correlation(int *xvals, int *yvals, int N)
Pointer to array of 100 ints:

int (*pa)[100];

Pointer to int:

int *p;

Those two types are *not* the same.
No, but int *p is not constrained to pointing at a memory object containing
only one integer.

Thank you for participating in this interview.
We have your resume on file. Don't call us,
we'll call you.

-Mike
 
M

Mike Wahler

Joona I Palaste said:
Dan Pop said:
In <[email protected]> Joona I Palaste
JV <[email protected]> scribbled the following:
What's 'wrong' with using multi-dimensional arrays,
and what will come to me if I use one?

I won't ask what you consider a 'fancy' declaration.

I think what confuses people learning C is that if you declare two arrays:

int a[10]
int b[10][10]

then a[0] is integer and b[0] is a pointer to integer.

It would confuse them, yes. Fortunately it's not true. b[0] is an
array of ten integers.
Which *immediately* decays into ... unless used as the operand of the
sizeof or unary & operators. This is the confusing bit.

Yes, I agree. It is the same situation with a one-dimensional array, so
arrays of arrays don't have any magical properties.
One way to understand the difference is to think of the raw bytes
comprising the objects. An array is simply several values (ints in
this case) put immediately after each other. Nothing more. There are
no array-specific bits or bytes involved.
A pointer, OTOH, is a value that constitutes the address of another
value. This address value is stored in the object, but the actual
values (ints in this case) it points to can be stored pretty much
anywhere. A pointer definitely has extra pointer-specific bits or
bytes involved - otherwise it wouldn't know where to point.
Arrays can't coincide or overlap each other, any more than normal
values (ints in this case) can. However, several pointers can point
at the same place, or inside each other's defined pointing range.
As usual, I may have been inaccurate at some points. Corrections are
welcome.

The only thing above I (mildly) object to is this part:
A pointer, OTOH, is a value that constitutes the address of another
value. This address value is stored in the object, but the actual
values ...

I'd change that to:

A pointer, OTOH, is an object that can represent the address of another
object. This address value is stored in the pointer object, but the actual
objects ...

IOW objects represent values, but not all values are objects.

-Mike
 
M

Mike Wahler

So you can't tell if
you see expression like a what it actually is without knowing the
declaration.


Correct, and this is the case with any statement referring
to an object, array or not.

i = j; /* we need to see declarations of 'i' and 'j' to
know what they are */
And I KNOW that arrays are not pointers and still I managed to
get it wrong in my previous post ...

Yes, slee can be a sippery slubject. :)

-Mike
 
J

Joe Laughlin

Me said:
Man the C teachers in college aren't doing their job!

At the university I recently graduated from, the professors didn't "teach"
languages. They used languages to show various CS concepts. Primarily, it
was done in C++, although the networking and OS classes used C. I think
this is rather typical.

Also, there seems to be a shift towards software engineering and away from
general computer science. Dunno if this is good or not. As a recent
graduate (this last week), I just started a new job, and I've found out that
I'm pretty rusty on pointers, bit-shifting/byte-packing techniques,
big/little-endians, etc. However, I feel that I'm pretty good at software
design, object-oriented programming, project management, etc.
 

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

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top