By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,015 Members | 1,023 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,015 IT Pros & Developers. It's quick & easy.

Array and Pointer Tutorial

P: n/a
Some programmers treat arrays just like pointers (and some even think that
they're exactly equivalent). I'm going to demonstrate the differences.

Firstly, let's assume that we're working on a platform which has the
following properties:

1) char's are 8-Bit. ( "char" is synomonous with "byte" ).
2) int's are 32-Bit. ( sizeof(int) == 4 ).
3) Pointers are 64-Bit. ( sizeof(int*) == 8 ).
First let's make two declarations:

int main(void)
{
int array[5];

int* const pointer = (int*)malloc( 5 * sizeof(int) );
}
Now I'll demonstrate how "array" and "pointer" are different:
I'll start off with simple analgous expressions:

================================================== ==========================
| Expression | Type and Access Specifiers | That in English |
================================================== ==========================
| | | |
| array | int[5] | An array of five int's.|
| | | |
|---------------------------------------------------------------------------
| | |A const pointer which |
| pointer | int* const |points to a modifiable |
| | |int. |
|--------------------------------------------------------------------------|
| | |A const pointer which |
| &array | int (* const)[5] |points to a modifiable |
| | |array of five int's. |
|--------------------------------------------------------------------------|
| | |A const pointer, which |
| &pointer | int* const* const |points to a const |
| | |pointer, which points to|
| | |a modifiable int. |
================================================== ==========================
Here's how "sizeof" works with them:
================================================== =========
| Expression | sizeof( exp ) | But Why? |
================================================== =========
| | | |
| array | 20 | It's five int's. |
| | (5 * 4) | |
|---------------------------------------------------------|
| | | |
| pointer | 8 | It's just a pointer.|
| | (just 8) | |
|---------------------------------------------------------|
| | | |
| &array | 8 | It's just a pointer.|
| | (just 8) | |
|----------------------------------------------------------
| | | |
| &pointer | 8 | It's just a pointer.|
| | | |
| | (just 8) | |
================================================== =========
Okay next thing to discuss is the usage of square brackets, and the
dereference operator. The two of these are to be used by pointers only. So
how come we can use them with arrays, as follows?:

array[0] = 4;

*array = 6;

The reason is that an expression of the following type:

int[5]

can implicitly convert to an expression of the following type:

int* const

What it does is convert to a pointer to the first element of the array.
Therefore, the first example:

array[0] = 4;

implicitly converts "array" to a normal pointer, then uses chain brackets to
access memory at a certain offset from the original address.

Also the second example:

*array = 6;

implicitly converts "array" to a normal pointer, then dereferences it.
NOTE: You must remember that an array implicitly converts to a pointer to
its first element, NOT to a pointer to the array. This fact has a few
implications. Here's one such implication:
*(array + 3) = 6;
What the above line of code does is the following:

1) Implicitly converts "array" to an: int* const
2) Adds 3 * sizeof(int) to the address.
3) Dereferences the resulting pointer, and assigns 6 to it.
If "array" implicitly converted to: int (*)[5]
rather than a pointer to the first element, then Step 2 above would be
different, specifically:
2) Adds 3 * sizeof( int[5] ) to the address.
And we know that sizeof(int[5]) is 20 on this platform (not 8!).
So you may ask, "What's the point in having a pointer to an array?" -- well
here's where it may come in handy:
void SomeFunc ( int (* const p_array)[5] )
{
(*p_array)[0] = 99;
(*p_array)[1] = 98;
(*p_array)[2] = 97;
(*p_array)[3] = 96;
(*p_array)[4] = 95;

/* This function won't accept an array of any
other size! */
}
And here's a C++-specific example with references:

void SomeFunc ( int (&array)[5] )
{
array[0] = 99;
array[1] = 98;
array[2] = 97;
array[3] = 96;
array[4] = 95;

/* This function won't accept an array of any
other size! */
}
Also in C++, you can exploit the use of templates:

template<class T, unsigned long len>
void KeepCopy( const T (&array)[len] )
{
static my_array[len];

/* Do some other stuff */
}
I've posted this to a few newsgroups, so if you'd like to reply, please post
to comp.lang.c because it's the common denominator. If your post is C++-
specific, the please post to comp.lang.c++.

Did I leave anything out?

-Tomás

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
May 11 '06 #1
Share this Question
Share on Google+
53 Replies


P: n/a
"Tomás" <NU**@NULL.NULL> wrote:
Some programmers treat arrays just like pointers (and some even think that
they're exactly equivalent). I'm going to demonstrate the differences.

Firstly, let's assume that we're working on a platform which has the
following properties:

1) char's are 8-Bit. ( "char" is synomonous with "byte" ).
A char is _always_ a byte. What you mean is that you are assuming a char
(and therefore also a byte) to be equal to an octet.
2) int's are 32-Bit. ( sizeof(int) == 4 ).
3) Pointers are 64-Bit. ( sizeof(int*) == 8 ).
First let's make two declarations:

int main(void)
{
int array[5];

int* const pointer = (int*)malloc( 5 * sizeof(int) );


*Boing* and here the demonstration crashes.

Never cast malloc(). It is not necessary. void *s can be freely
converted to and from any object pointer type.
Never use malloc() (or any other function, for that matter) without a
proper declaration in scope. It forces your compiler to assume that the
function returns an int, which malloc() clearly does not.

Note that the first error hides the second. The combination of the two
can result in garbage being assigned to your pointer.

As a matter of convenient maintenance, not a true error, it is more
dabble-proof to use sizeof *pointer rather than sizeof (type). If your
pointer's type changes, the first form stays correct, the second can
turn deceptively (and hiddenly!) broken.

All in all, that program should've looked like this:

#include <stdlib.h>

int main(void)
{
int array[5];

int* const pointer = malloc(5 * sizeof *pointer);
}

Anyway, the difference between pointers and arrays is most simply
demonstrated using the age[1]-old method of arrows and groups of boxes.

Richard

[1] I.e., in the computing world, a couple of decades
May 11 '06 #2

P: n/a
Tomás wrote:
Some programmers treat arrays just like pointers (and some even think that
they're exactly equivalent). I'm going to demonstrate the differences.


Some of these days you can also write an article demonstrating that integer
types are not floating point types. It will be another great contribution
to the progress of humanity.

--
Salu2

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php
May 11 '06 #3

P: n/a
As a matter of convenient maintenance, not a true error, it is more
dabble-proof to use sizeof *pointer rather than sizeof (type). If your
pointer's type changes, the first form stays correct, the second can
turn deceptively (and hiddenly!) broken.

All in all, that program should've looked like this:

#include <stdlib.h>

int main(void)
{
int array[5];

int* const pointer = malloc(5 * sizeof *pointer);
}

Anyway, the difference between pointers and arrays is most simply
demonstrated using the age[1]-old method of arrows and groups of boxes.

Richard

[1] I.e., in the computing world, a couple of decades


Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *array);

return 0;
}
Now, I change
int array[5];

to

double array[5];

Wouldn't the sizeof double be truncated to the sizeof int? If so, the
wouldn't this create an additional bug?

Chad

May 11 '06 #4

P: n/a
Chad wrote:
As a matter of convenient maintenance, not a true error, it is more
dabble-proof to use sizeof *pointer rather than sizeof (type). If your
pointer's type changes, the first form stays correct, the second can
turn deceptively (and hiddenly!) broken.

All in all, that program should've looked like this:

#include <stdlib.h>

int main(void)
{
int array[5];

int* const pointer = malloc(5 * sizeof *pointer);
}

Anyway, the difference between pointers and arrays is most simply
demonstrated using the age[1]-old method of arrows and groups of boxes.

Richard

[1] I.e., in the computing world, a couple of decades


Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *array);

return 0;
}
Now, I change
int array[5];

to

double array[5];

Wouldn't the sizeof double be truncated to the sizeof int? If so, the
wouldn't this create an additional bug?


You have not followed the suggested practice of using sizeof *pointer
being assigned to. Your example should have been:
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *q);

return 0;
}

Or, if you want array and q to always be the same type, you could have used:
#include <stdlib.h>
int main(void) {
int array[5], *q = malloc(sizeof *q);

return 0;
}

I really can't see why you would think of using sizeof some other object.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php
May 11 '06 #5

P: n/a
Chad wrote:
.... snip ...
Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *array);


There is no such thing as *array. array is an array of 5 integers,
not a pointer.

--
Some informative links:
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
May 11 '06 #6

P: n/a
CBFalconer wrote:

Chad wrote:

... snip ...

Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *array);


There is no such thing as *array. array is an array of 5 integers,
not a pointer.

"array[0]" is the same as "*(array+0)" which simplifies to "*array".
--
+----------------------------------------------------------------+
| Charles and Francis Richmond richmond at plano dot net |
+----------------------------------------------------------------+
May 11 '06 #7

P: n/a
CBFalconer wrote:

Chad wrote:

int array[5];

int *q = malloc(sizeof *array);


There is no such thing as *array. array is an array of 5 integers,
not a pointer.


(*array) is an expression of type int.

The operand of sizeof is (*array), not (array),
so, array gets converted to a pointer.

--
pete
May 11 '06 #8

P: n/a
Charles Richmond wrote:
CBFalconer wrote:
Chad wrote:
>

... snip ...

Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *array);


There is no such thing as *array. array is an array of 5 integers,
not a pointer.


"array[0]" is the same as "*(array+0)" which simplifies to "*array".


When array is passed as a parameter, which this one isn't.

--
Some informative links:
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
May 11 '06 #9

P: n/a
CBFalconer posted:

"array[0]" is the same as "*(array+0)" which simplifies to "*array".


When array is passed as a parameter, which this one isn't.

Stop trolling and propogating misinformation.

"array" implicitly converts to a pointer to its first element ALL THE TIME
-- NOT just when passed as an argument to a function, NOT just when it's a
global variable, NOT just when you have porridge instead of cereal.

-Tomás
May 12 '06 #10

P: n/a

Tomás wrote:
CBFalconer posted:

"array[0]" is the same as "*(array+0)" which simplifies to "*array".


When array is passed as a parameter, which this one isn't.

Stop trolling and propogating misinformation.

"array" implicitly converts to a pointer to its first element ALL THE TIME
-- NOT just when passed as an argument to a function, NOT just when it's a
global variable, NOT just when you have porridge instead of cereal.


I keep trying to compile the following program:

void f(char *b) {
b++;
}

int main(void) {
char a[]={'a','b','c'};

a++;

f(a);

return 0;
}

Let me know where it fails on your C compiler as a should implicitly
convert to a pointer, right?

--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)

May 12 '06 #11

P: n/a
Nelu wrote:

Tomás wrote:
CBFalconer posted:

> "array[0]" is the same as "*(array+0)"
> which simplifies to "*array".

When array is passed as a parameter, which this one isn't.

Stop trolling and propogating misinformation.

"array" implicitly converts to a pointer to its first element
ALL THE TIME
-- NOT just when passed as an argument to a function,
NOT just when it's a
global variable, NOT just when you have porridge instead of cereal.


Stop trolling and propogating misinformation.

An expression of array type is not coverted
when it is the operand of the sizeof operator.
An expression of array type is not coverted
when it is the operand of the address operator.
I keep trying to compile the following program: int main(void) {
char a[]={'a','b','c'};

a++; Let me know where it fails on your C compiler as a should implicitly
convert to a pointer, right?


"(8) : error C2105: '++' needs l-value"

One problem with (a++),
is that the result of a type conversion is not an lvalue.

N869
6.3.2 Other operands
6.3.2.1 Lvalues and function designators

[#3] 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.

--
pete
May 12 '06 #12

P: n/a

pete wrote:
Nelu wrote:

Tomás wrote:
CBFalconer posted:
>> "array[0]" is the same as "*(array+0)"
>> which simplifies to "*array".
>
> When array is passed as a parameter, which this one isn't.
Stop trolling and propogating misinformation.

"array" implicitly converts to a pointer to its first element
ALL THE TIME
-- NOT just when passed as an argument to a function,
NOT just when it's a
global variable, NOT just when you have porridge instead of cereal.


Stop trolling and propogating misinformation.

An expression of array type is not coverted
when it is the operand of the sizeof operator.
An expression of array type is not coverted
when it is the operand of the address operator.
I keep trying to compile the following program:

int main(void) {
char a[]={'a','b','c'};

a++;

Let me know where it fails on your C compiler as a should implicitly
convert to a pointer, right?


"(8) : error C2105: '++' needs l-value"

One problem with (a++),
is that the result of a type conversion is not an lvalue.

N869
6.3.2 Other operands
6.3.2.1 Lvalues and function designators

[#3] 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.


If it's not an lvalue doesn't it mean that it's not a pointer *object*
but a pointer value?

--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)

May 12 '06 #13

P: n/a
If it's not an lvalue doesn't it mean that it's not a pointer *object*
but a pointer value?

From the Standard:

An lvalue refers to an object or function. Some rvalue expressions —-
those of class or cv-qualified class type -- also refer to objects.
-Tomás
May 12 '06 #14

P: n/a
Nelu wrote:

pete wrote:
Nelu wrote:

Tomás wrote:
> CBFalconer posted:
>
>
> >> "array[0]" is the same as "*(array+0)"
> >> which simplifies to "*array".
> >
> > When array is passed as a parameter, which this one isn't.
>
>
> Stop trolling and propogating misinformation.
>
> "array" implicitly converts to a pointer to its first element
> ALL THE TIME
> -- NOT just when passed as an argument to a function,
> NOT just when it's a
> global variable, NOT just when you have porridge instead of cereal.


Stop trolling and propogating misinformation.

An expression of array type is not coverted
when it is the operand of the sizeof operator.
An expression of array type is not coverted
when it is the operand of the address operator.
I keep trying to compile the following program:

int main(void) {
char a[]={'a','b','c'};

a++;

Let me know where it fails on your C compiler
as a should implicitly
convert to a pointer, right?


"(8) : error C2105: '++' needs l-value"

One problem with (a++),
is that the result of a type conversion is not an lvalue.

N869
6.3.2 Other operands
6.3.2.1 Lvalues and function designators

[#3] 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.


If it's not an lvalue doesn't it mean that it's not a pointer *object*
but a pointer value?


Yes.

(a++) means the same thing as ((a + 0)++)

--
pete
May 12 '06 #15

P: n/a
Tomás wrote:
Some rvalue expressions —-
those of class or cv-qualified class type -- also refer to objects.


What does "class or cv-qualified class type" mean?

Is that C++?

--
pete
May 12 '06 #16

P: n/a
You have not followed the suggested practice of using sizeof *pointer
being assigned to. Your example should have been:
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *q);

return 0;
}

Or, if you want array and q to always be the same type, you could have used:
#include <stdlib.h>
int main(void) {
int array[5], *q = malloc(sizeof *q);

return 0;
}

I really can't see why you would think of using sizeof some other object.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php


I can't really put me pinpoint the exact part, but I know I'm missing
some kind of underlying concept when I see the construction:

int *q = malloc(sizeof *q);

Maybe when I'm scrubbing the dairy coolers at work tomorrow morning,
the exact part that is irking me will set in. Then I can come back and
ask the EXACT question about the construction.

Chad

May 12 '06 #17

P: n/a
Chad said:

I can't really put me pinpoint the exact part, but I know I'm missing
some kind of underlying concept when I see the construction:

int *q = malloc(sizeof *q);


The canonical way to allocate space for n objects of type T is:

T *p = malloc(n * sizeof *p);

or, if p is already declared, simply this:

p = malloc(n * sizeof *p);

The reason this is the canonical way is that it doesn't rely on the type of
p, except that it must be an object type, not an incomplete type or
function type. If the type of p changes during maintenance, you don't have
to hunt down this line and hack it about. It will automagically work
correctly with the new type.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 12 '06 #18

P: n/a
On Thu, 11 May 2006 11:25:49 -0400, CBFalconer <cb********@yahoo.com>
wrote in comp.lang.c:
Chad wrote:

... snip ...

Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *array);


There is no such thing as *array. array is an array of 5 integers,
not a pointer.


I beg your pardon. There most definitely is such a thing as *array,
because of the implicit and automatic conversion of the name of an
array to a pointer in all expressions other than unary & and sizeof.

Compile and execute yourself:

#include <stdio.h>

int main(void)
{
double array1 [10];
char array2 [10];

printf("sizeof *array1 = %d\n", (int)sizeof *array1);
printf("sizeof *array2 = %d\n", (int)sizeof *array2);

return 0;
}

I get:

sizeof *array1 = 8
sizeof *array2 = 1
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
May 12 '06 #19

P: n/a
Richard Heathfield wrote:
Chad said:

I can't really put me pinpoint the exact part, but I know I'm missing
some kind of underlying concept when I see the construction:

int *q = malloc(sizeof *q);


The canonical way to allocate space for n objects of type T is:

T *p = malloc(n * sizeof *p);

or, if p is already declared, simply this:

p = malloc(n * sizeof *p);

The reason this is the canonical way is that it doesn't rely on the type of
p, except that it must be an object type, not an incomplete type or
function type. If the type of p changes during maintenance, you don't have
to hunt down this line and hack it about. It will automagically work
correctly with the new type.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)


Hmmm... It looks like got a response before I could correct the grammar
errors in my previous post. Anyhow, I think I managed to pinpoint what
is irking me.

Say I have the following:

/*I omitted checking malloc() for NULL and forgot to use free()*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
char *p = malloc(sizeof *p);
/* incomplete -- malloc's return value not checked */
strcpy(p, "Hello, world!");

return 0;
}

Are you saying that the construction
char *p = malloc(sizeof *p);

would allocate enough space to hold the string ""Hello, world!" versus
allocating memory to hold just one char?

Chad

May 12 '06 #20

P: n/a
Chad wrote:
Hmmm... It looks like got a response before I could correct the grammar
errors in my previous post. Anyhow, I think I managed to pinpoint what
is irking me.

Say I have the following:

/*I omitted checking malloc() for NULL and forgot to use free()*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
char *p = malloc(sizeof *p);
/* incomplete -- malloc's return value not checked */
strcpy(p, "Hello, world!");
Bang! sizeof *p == sizeof char == 1.
return 0;
}

Are you saying that the construction
char *p = malloc(sizeof *p);

would allocate enough space to hold the string ""Hello, world!" versus
allocating memory to hold just one char?

The answer has to be 1.

--
Ian Collins.
May 12 '06 #21

P: n/a
Chad wrote:
Richard Heathfield wrote:
Chad said:

I can't really put me pinpoint the exact part, but I know I'm
missing some kind of underlying concept when I see the construction:

int *q = malloc(sizeof *q);


The canonical way to allocate space for n objects of type T is:

T *p = malloc(n * sizeof *p);

or, if p is already declared, simply this:

p = malloc(n * sizeof *p);

The reason this is the canonical way is that it doesn't rely on the
type of p, except that it must be an object type, not an incomplete
type or function type. If the type of p changes during maintenance,
you don't have to hunt down this line and hack it about. It will
automagically work correctly with the new type.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)


Hmmm... It looks like got a response before I could correct the
grammar errors in my previous post. Anyhow, I think I managed to
pinpoint what is irking me.

Say I have the following:

/*I omitted checking malloc() for NULL and forgot to use free()*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
char *p = malloc(sizeof *p);
/* incomplete -- malloc's return value not checked */
strcpy(p, "Hello, world!");

return 0;
}

Are you saying that the construction
char *p = malloc(sizeof *p);

would allocate enough space to hold the string ""Hello, world!" versus
allocating memory to hold just one char?

As p points to a char, *p is a char, so sizeof *p is 1 [*but* no dereference
is actually performed].

The point being made is, say you have this ...

char *p = malloc(sizeof char);

but later change the *p to this ...

int *p = malloc(sizeof char);

You have an error here, as char is still used with sizeof.
However, if you have this ...

char *p = malloc(sizeof *p);

but later change it to this ...

int *p = malloc(sizeof *p);

things are ok, and the sun still rises every day.
--
==============
Not a pedant
==============
May 12 '06 #22

P: n/a
Chad said:
Richard Heathfield wrote:
<snip>
p = malloc(n * sizeof *p);
<snip>
Are you saying that the construction
char *p = malloc(sizeof *p);

would allocate enough space to hold the string ""Hello, world!"


Which letter of 'n' were you struggling with?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 12 '06 #23

P: n/a
Chad wrote:
Richard Heathfield wrote:
Chad said:
I can't really put me pinpoint the exact part, but I know I'm missing
some kind of underlying concept when I see the construction:

int *q = malloc(sizeof *q); The canonical way to allocate space for n objects of type T is:

T *p = malloc(n * sizeof *p);

or, if p is already declared, simply this:

p = malloc(n * sizeof *p);

The reason this is the canonical way is that it doesn't rely on the type of
p, except that it must be an object type, not an incomplete type or
function type. If the type of p changes during maintenance, you don't have
to hunt down this line and hack it about. It will automagically work
correctly with the new type.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)


Please snip peoples sigs (the bit usually after a '-- ') unless you are
commenting on them.
Hmmm... It looks like got a response before I could correct the grammar
errors in my previous post. Anyhow, I think I managed to pinpoint what
is irking me.

Say I have the following:

/*I omitted checking malloc() for NULL and forgot to use free()*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
char *p = malloc(sizeof *p);
/* incomplete -- malloc's return value not checked */
strcpy(p, "Hello, world!");

return 0;
}

Are you saying that the construction
char *p = malloc(sizeof *p);

would allocate enough space to hold the string ""Hello, world!" versus
allocating memory to hold just one char?


No, because p is not of type 'pointer to "Hello, world'". Remember that
a string is an array of char, not a single char. C does not have a
string type.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
May 12 '06 #24

P: n/a
Richard Heathfield wrote:

Chad said:
Richard Heathfield wrote:
<snip>
p = malloc(n * sizeof *p);
<snip>

Are you saying that the construction
char *p = malloc(sizeof *p);


He said "for n objects of type T"
would allocate enough space to hold the string ""Hello, world!"


Which letter of 'n' were you struggling with?


I generally consider three different malloc situations:

1 "n objects of type T"
T *p = malloc(n * sizeof *p);
T *p = malloc(sizeof *p); /* when n == 1 */

2 string
char *p = malloc(length + 1);
char *p = malloc(sizeof "string_literal");

3 pointer to type void
void *p = malloc(sizeof object_identifier);

p = malloc(sizeof car);
*(struct vehicle *)p = car;

--
pete
May 12 '06 #25

P: n/a

pete wrote:
Richard Heathfield wrote:

Chad said:
Richard Heathfield wrote:
>

<snip>
>
> p = malloc(n * sizeof *p);
>

<snip>

Are you saying that the construction
char *p = malloc(sizeof *p);
He said "for n objects of type T"
would allocate enough space to hold the string ""Hello, world!"


Which letter of 'n' were you struggling with?


I generally consider three different malloc situations:

1 "n objects of type T"
T *p = malloc(n * sizeof *p);
T *p = malloc(sizeof *p); /* when n == 1 */

2 string
char *p = malloc(length + 1);
char *p = malloc(sizeof "string_literal");

3 pointer to type void
void *p = malloc(sizeof object_identifier);

p = malloc(sizeof car);
*(struct vehicle *)p = car;

--
pete


The statement "for n objects of type T" didn't immediately register in
my snoodle. Anyhow after sleeping for 3 hours and re-reading the post,
the entire thing makes sense.

Chad

May 12 '06 #26

P: n/a
pete wrote:
Richard Heathfield wrote:

Chad said:
Richard Heathfield wrote:
>

<snip>
>
> p = malloc(n * sizeof *p);
>

<snip>

Are you saying that the construction
char *p = malloc(sizeof *p);
He said "for n objects of type T"
would allocate enough space to hold the string ""Hello, world!"


Which letter of 'n' were you struggling with?


I generally consider three different malloc situations:

1 "n objects of type T"
T *p = malloc(n * sizeof *p);
T *p = malloc(sizeof *p); /* when n == 1 */

2 string
char *p = malloc(length + 1);
char *p = malloc(sizeof "string_literal");

3 pointer to type void
void *p = malloc(sizeof object_identifier);

p = malloc(sizeof car);
*(struct vehicle *)p = car;

--
pete


The statement "for n objects of type T" didn't immediately register in
my snoodle. Anyhow after sleeping for 3 hours and re-reading the posts,
the entire thread makes sense.

Chad

May 12 '06 #27

P: n/a
"Tomás" wrote:
CBFalconer posted:
"array[0]" is the same as "*(array+0)" which simplifies to "*array".


When array is passed as a parameter, which this one isn't.


Stop trolling and propogating misinformation.

"array" implicitly converts to a pointer to its first element ALL THE
TIME -- NOT just when passed as an argument to a function, NOT just
when it's a global variable, NOT just when you have porridge instead
of cereal.


You are woefully misinformed. Try:

#include <stdio.h>

int a[5];

int main(void)
{
printf("*a=%lu\n", (unsigned long)sizeof(*a));
printf(" a=%lu\n", (unsigned long)sizeof(a));
return 0;
}

/* expected output on my system:
*a=4
a=20
*/

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
May 12 '06 #28

P: n/a

"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:S_********************@bt.com...
Chad said:

I can't really put me pinpoint the exact part, but I know I'm missing
some kind of underlying concept when I see the construction:

int *q = malloc(sizeof *q);
The canonical way to allocate space for n objects of type T is:

T *p = malloc(n * sizeof *p);

or, if p is already declared, simply this:

p = malloc(n * sizeof *p);

The reason this is the canonical way is that it doesn't rely on the type

of p, except that it must be an object type, not an incomplete type or
function type. If the type of p changes during maintenance, you don't have
to hunt down this line and hack it about. It will automagically work
correctly with the new type.


You should point out the negatives too. If p is already declared, and their
is no comment telling him what file p is declared in. He'll spend forever
trying to answer this question: "What the HELL is p?"

p = malloc(n * sizeof *p); /* p orignially was of type T and declared in
file somedecl.h */
Rod Pemberton

May 12 '06 #29

P: n/a
Rod Pemberton said:
You should point out the negatives too. If p is already declared, and
their
is no comment telling him what file p is declared in. He'll spend forever
trying to answer this question: "What the HELL is p?"


Oh, please try to /think/ before posting. You don't need that crutch with
all your other objects, so why on earth would you need it with objects that
you happen to be pointing at the return value of a malloc call?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 12 '06 #30

P: n/a

"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:7J******************************@bt.com...
Rod Pemberton said:
You should point out the negatives too. If p is already declared, and
their
is no comment telling him what file p is declared in. He'll spend forever trying to answer this question: "What the HELL is p?"
Oh, please try to /think/ before posting. You don't need that crutch with
all your other objects, so why on earth would you need it with objects

that you happen to be pointing at the return value of a malloc call?
You don't need that crutch with all your other objects
True. But, I wrote the code.
so why on earth would you need it with objects that
you happen to be pointing at the return value of a
malloc call?


Because, you mentioned _maintenance_ of code which the OP likely didn't
write:
RH: "If the type of p changes during maintenance"

Perhaps, you should /remember/ what you wrote before declaring that I need
to /think/.
Rod Pemberton
May 12 '06 #31

P: n/a
Rod Pemberton said:

"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:7J******************************@bt.com...
You don't need that crutch with all your other objects


True. But, I wrote the code.


The same, however, is true for maintenance programmers. You don't provide
that crutch for them with other objects, so why provide it here?

Please learn to think before replying.
so why on earth would you need it with objects that
you happen to be pointing at the return value of a
malloc call?


Because, you mentioned _maintenance_ of code which the OP likely didn't
write:
RH: "If the type of p changes during maintenance"

Perhaps, you should /remember/ what you wrote before declaring that I need
to /think/.


Oh, but I did. And the fact remains that it is inconsistent and pointless to
provide an asinine type-reminder crutch in one special circumstance when
one doesn't provide asinine type-reminder crutches in general. Your
argument falls because, if it made sense at all, it would make sense in all
situations where an object is used - which it clearly doesn't.

But no, I realise there's no point trying to get you to understand this. Be
happy, have fun, and enjoy the colour of the sky on whatever planet you
happen to be occupying right now.
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 12 '06 #32

P: n/a
Rod Pemberton wrote:
"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:7J******************************@bt.com...
Rod Pemberton said:
You should point out the negatives too. If p is already declared, and
their
is no comment telling him what file p is declared in. He'll spend forever trying to answer this question: "What the HELL is p?"

Oh, please try to /think/ before posting. You don't need that crutch with
all your other objects, so why on earth would you need it with objects

that
you happen to be pointing at the return value of a malloc call?

You don't need that crutch with all your other objects


True. But, I wrote the code.
so why on earth would you need it with objects that
you happen to be pointing at the return value of a
malloc call?


Because, you mentioned _maintenance_ of code which the OP likely didn't
write:
RH: "If the type of p changes during maintenance"

Perhaps, you should /remember/ what you wrote before declaring that I need
to /think/.


That doesn't invalidate Richard's point. The maintenance programmer
doesn't normally get that for all other object types.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
May 13 '06 #33

P: n/a

"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:D7********************@bt.com...
Rod Pemberton said:

"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:7J******************************@bt.com...
You don't need that crutch with all your other objects
True. But, I wrote the code.


The same, however, is true for maintenance programmers.


Not so.
You don't provide
that crutch for them with other objects, so why provide it here?
We were talking about when the allocation and declaration were separated.

Please learn to think before replying.

Please learn to read and remember before replying.
so why on earth would you need it with objects that
you happen to be pointing at the return value of a
malloc call?


Because, you mentioned _maintenance_ of code which the OP likely didn't
write:
RH: "If the type of p changes during maintenance"

Perhaps, you should /remember/ what you wrote before declaring that I need to /think/.


Oh, but I did.


Yeah right...
And the fact remains that it is inconsistent and pointless to
provide an asinine type-reminder crutch in one special circumstance when
one doesn't provide asinine type-reminder crutches in general. Your
argument falls because, if it made sense at all, it would make sense in all situations where an object is used - which it clearly doesn't.


The argument makes sense. Have you ever programmed? In C? Have you ever
written 500 thousand plus lines of code for the same application? Have you
ever worked on a 3 million plus line program? Have you ever had to deal
with 500+ _identical_ if statements because some maintenance progarmmer 15
years earlier decided not to write a procedure and all others who followed
did the same? I have. I know what I'm talking about. Your inaccurate
perception and downplaying of this issue as triviality is ludicrous.
Rod Pemberton
May 13 '06 #34

P: n/a
Rod Pemberton said:

"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:D7********************@bt.com...
Rod Pemberton said:
>
> "Richard Heathfield" <in*****@invalid.invalid> wrote in message
> news:7J******************************@bt.com...
>
>> You don't need that crutch with all your other objects
>
> True. But, I wrote the code.


The same, however, is true for maintenance programmers.


Not so.


I think we remain firmly on different planets. I see no purpose in
continuing this discussion.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 13 '06 #35

P: n/a
CBFalconer <cb********@yahoo.com> writes:
Charles Richmond wrote:
CBFalconer wrote:
Chad wrote:
>
... snip ...

Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array[5];

int *q = malloc(sizeof *array);

There is no such thing as *array. array is an array of 5 integers,
not a pointer.


"array[0]" is the same as "*(array+0)" which simplifies to "*array".


When array is passed as a parameter, which this one isn't.


Sorry, you've blown this one.

An expression of array type is implicitly converted to a pointer to its
first element *unless*:
It's the operand of a sizeof operator, or
It's the operand of a unary "&" operator, or
It's a string literal used to initialize an array.

Passing it as a parameter is irrelevant.

The behavior of any one implementation doesn't prove anything, but
this works:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int array[5];
double another_array[10];
size_t s1 = sizeof *array;
size_t s2 = sizeof *another_array;
printf("s1 = %d, s2 = %d\n", (int)s1, (int)s2);
return 0;
}

and prints "s1 = 4, s2 = 8" on my system (matching sizeof(int) and
sizeof(double)).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 14 '06 #36

P: n/a
"Tomás" <NU**@NULL.NULL> writes:
CBFalconer posted:
"array[0]" is the same as "*(array+0)" which simplifies to "*array".
When array is passed as a parameter, which this one isn't.


Stop trolling and propogating misinformation.


If you've been following this newsgroup, you should know that
CBFalconer is no troll. He's made an honest mistake in this case.
It happens.
"array" implicitly converts to a pointer to its first element ALL THE TIME
-- NOT just when passed as an argument to a function, NOT just when it's a
global variable, NOT just when you have porridge instead of cereal.


Oh, look, it just happened again. (An array name is not converted to
a pointer if it's the operand of a "sizeof" or unary "&" operator.)
But even though you don't have anything like CBFalconer's reputation
here, I'm not going to assume you're a troll.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 14 '06 #37

P: n/a

Keith Thompson wrote:
CBFalconer <cb********@yahoo.com> writes:

<snip>

When array is passed as a parameter, which this one isn't.


Sorry, you've blown this one.

An expression of array type is implicitly converted to a pointer to its
first element *unless*:
It's the operand of a sizeof operator, or
It's the operand of a unary "&" operator, or
It's a string literal used to initialize an array.

Passing it as a parameter is irrelevant.

The behavior of any one implementation doesn't prove anything, but
this works:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int array[5];
double another_array[10];
size_t s1 = sizeof *array;
size_t s2 = sizeof *another_array;
printf("s1 = %d, s2 = %d\n", (int)s1, (int)s2);
return 0;
}

and prints "s1 = 4, s2 = 8" on my system (matching sizeof(int) and
sizeof(double)).


Forgive me, but I still think CBFalconer is right. I think it's more of
a discussion related to whether an array is a const pointer or it's an
rvalue which makes it an address value which is what a pointer contains
but it's not a pointer object.

The first idea may be implementation dependent. I tried it with gcc.
Let's say you have int a[10] and try a++. Now, if it were a constant
gcc would complain: increment of read only variable. In this case it
says wrong type of argument to increment. This sounds like it's not a
const pointer but just the address of the pointer (which is correct
since &a, a and &a[0] have the same value, so the pointer (&a) has the
same address as it's value (a). It can be argued that this is
implementation dependent, I guess.
The second idea is to see how it works:

1).
int a[10];
a[2]=3;

2).
int *b=malloc(10*sizeof(int));
b[2]=3;

In the first case we have the address value a, so:
Step 1: Go to positions forward from a[0]
Step 2: At the address put 3

In the second case we have:
Step 1: Get the value contained in b
Step 2: Add two positions to it
Step 3: Set the value the the address 3.

I guess it can be argued that this is also implementation dependent
since you could get the address value of a from &a (since they're
equal) but I doubt that happens.

It seems it may be that the implementation dictates the choice of words
:-).

If the array is an rvalue, when passed to a function like f(int *arr),
arr will behave like a pointer in any case, independent of
implementation.
--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)

May 14 '06 #38

P: n/a

Nelu wrote:
Keith Thompson wrote: <snip>
Passing it as a parameter is irrelevant.

<snip>

I'm not sure how irrelevant it is. Check this code:

void foo(char b[]) {
b++;
printf("%ld\t%ld\n",sizeof(b),sizeof(char*));
}

int main(void) {
char arr[10];
foo(arr);
printf("%ld\n",sizeof(arr));

return 0;
}

It seems that this is supposed to compile on any compiler (haven't
actually compiled it on every compiler there is, but I heard about it a
long time ago). It doesn't complain when you try to increment b (as an
argument it certainly doesn't seem to be a const pointer) in foo and
sizeof(b) should be different from sizeof(arr).
--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)


May 14 '06 #39

P: n/a
"Nelu" <ta********@gmail.com> writes:
Nelu wrote:
Keith Thompson wrote: <snip>
> Passing it as a parameter is irrelevant.

<snip>

I'm not sure how irrelevant it is. Check this code:

void foo(char b[]) {
b++;
printf("%ld\t%ld\n",sizeof(b),sizeof(char*));
}


b is not an array; it's a pointer object. And it's not a const
object; it's merely initialized to the value of the actual argument.

In a parameter declaration, "char b[]" is merely an alias for "char *b".
This is independent of the rules for implicit conversion of array
names to pointer values.

Also, "%ld" is not the correct format for a size_t. You can use "%zu"
if your library conforms to C99, or you can convert the operand to
the expected type:
printf("%d\t%d\n", (int)sizeof b, (int)sizeof(char*));
int main(void) {
char arr[10];
foo(arr);
Here arr is converted to a pointer value, equivalent to &arr[0].
This value is passed to foo and copied to b.
printf("%ld\n",sizeof(arr));

return 0;
}

[snip]

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 14 '06 #40

P: n/a

Keith Thompson wrote:
"Nelu" <ta********@gmail.com> writes:
Nelu wrote:
Keith Thompson wrote: <snip>
> Passing it as a parameter is irrelevant.

<snip>

I'm not sure how irrelevant it is. Check this code:

void foo(char b[]) {
b++;
printf("%ld\t%ld\n",sizeof(b),sizeof(char*));
}


b is not an array; it's a pointer object. And it's not a const
object; it's merely initialized to the value of the actual argument.

In a parameter declaration, "char b[]" is merely an alias for "char *b".
This is independent of the rules for implicit conversion of array
names to pointer values.

Also, "%ld" is not the correct format for a size_t. You can use "%zu"
if your library conforms to C99, or you can convert the operand to
the expected type:
printf("%d\t%d\n", (int)sizeof b, (int)sizeof(char*));
int main(void) {
char arr[10];
foo(arr);


Here arr is converted to a pointer value, equivalent to &arr[0].
This value is passed to foo and copied to b.
printf("%ld\n",sizeof(arr));

return 0;
}

[snip]


I didn't use %zu (although it works on my gcc) just in case someone
tries it on Turbo C :-). I forgot to cast, though, and -Wall didn't say
anything, probably because they are the same type.

The example was just to show that b (in foo) is a pointer object in
accordance with what CBFalconer was saying.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


May 14 '06 #41

P: n/a

Nelu wrote:
<snip>
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


Sorry, I forgot to snip your signature from my previous post and paste
mine. I guess this is a sign I should go to sleep :-).

--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)

May 14 '06 #42

P: n/a
Nelu wrote:

Keith Thompson wrote:
CBFalconer <cb********@yahoo.com> writes: <snip>

When array is passed as a parameter, which this one isn't.


Sorry, you've blown this one.

An expression of array type is
implicitly converted to a pointer to its
first element *unless*:
It's the operand of a sizeof operator, or
It's the operand of a unary "&" operator, or
It's a string literal used to initialize an array.

Passing it as a parameter is irrelevant.

Forgive me, but I still think CBFalconer is right.


It's time to quote the standard:

N869
6.3.2 Other operands
6.3.2.1 Lvalues and function designators

[#3] 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.
--
pete
May 14 '06 #43

P: n/a
pete wrote:

Nelu wrote:

Keith Thompson wrote:
CBFalconer <cb********@yahoo.com> writes: <snip>
>
> When array is passed as a parameter, which this one isn't.

Sorry, you've blown this one.

An expression of array type is
implicitly converted to a pointer to its
first element *unless*:
It's the operand of a sizeof operator, or
It's the operand of a unary "&" operator, or
It's a string literal used to initialize an array.

Passing it as a parameter is irrelevant.

Forgive me, but I still think CBFalconer is right.


It's time to quote the standard:


I see I already did this on Thursday.
What's the problem, Nelu?
N869
6.3.2 Other operands
6.3.2.1 Lvalues and function designators

[#3] 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.


--
pete
May 14 '06 #44

P: n/a
pete posted:
[#3] 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.


The reason they can put that in the Standard is that they've thought up of
every conceivable place where you can use an array as an array -- there's
only three such places, so it was handy to list them all.

In C++, we treat the array-to-pointer conversion just like any other
implicit conversion (e.g. char to int).

If we have a char:

char k;

It will remain as a char unless it needs to convert. For example:

void TakesAnInt( int r ) {}

int main(void) { char k; TakesAnInt(k); }

Just because a "char" can implicitly convert to an "int" doesn't mean
"char" is any less of a fully-fledged object type.

If we were able to pass arrays by value in C, then they'd have to remove
that paragraph from the Standard (or perhaps add the fourth instance where
you can use an array as an array).

In C++, we have references, and we can pass arrays by reference, so we tend
to look at it from the opposite viewpoint of C programmers.
Instead of thinking:
"When is an array actually an array, instead of being a pointer?"

We think:
"When does the array decay to a pointer?"

The most obvious place where we need to convert from array to pointer is by
the dereference operator:

*array /* You can't dereference an array, so it has
to become a pointer to its first element */
or by block brackets:

array[5] = 2; /* You can't use block-brackets with an array,
so it has to become a pointer to its first
element. */

Or by arithmetic:

array + 3 /* You can't use '+' with an array, so it has to
become a pointer to its first element */

Now that we know that an array will always be an array unless it needs to
convert to a pointer, we can pass arrays by reference:

void SomeFunc( int (&array)[20] )
{

}

int main()
{
int array[20];

SomeFunc( array );
}

The dandy thing about this way of thinking is that it works perfectly for C
aswell.

A char is a char, not an int (but it's more than happy to convert if it
needs to).

An array is an array, not a pointer (but it's more than happy to convert if
it needs to).

As C++ is constantly being developed and expanded upon, it's more
appropriate to state where an array decays to a pointer, rather than where
an array actually stays as an array.

Moral of the story: An array is an array -- not a pointer.

-Tomás
May 14 '06 #45

P: n/a
"Tomás" wrote:
pete posted:
[#3] 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.


The reason they can put that in the Standard is that they've thought
up of every conceivable place where you can use an array as an array
-- there's only three such places, so it was handy to list them all.

In C++, we treat the array-to-pointer conversion just like any other
implicit conversion (e.g. char to int).


if you look closely you will see that this newsgroup is
comp.lang.c, not comp.lang.c++.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
May 14 '06 #46

P: n/a
CBFalconer wrote:

"Tomás" wrote:
pete posted:
if you look closely you will see that this newsgroup is
comp.lang.c, not comp.lang.c++.


I looked at the original post and found:

"I've posted this to a few newsgroups,
so if you'd like to reply,
please post to comp.lang.c
because it's the common denominator.
If your post is C++-specific,
the please post to comp.lang.c++."

I think it was a mistake to post here.

Elsewhere on this thread he quoted a part of the C++ standard
and refered to it as "the Standard".

--
pete
May 15 '06 #47

P: n/a
Tomás wrote:
In C++, we treat the array-to-pointer conversion just like any other
implicit conversion (e.g. char to int).


In C, there is no typical implicit conversion for your phrase
"just like any other implicit conversion", to refer to.

The rules for implicit conversion varry by type.
There are different rules for the implicit conversions of
expressions of:
function type,
array type,
arithmetic type lower ranking than int,
other arithmetic types,
pointer types.

--
pete
May 15 '06 #48

P: n/a
On 13 May 2006 23:22:09 -0700, "Nelu" <ta********@gmail.com> wrote:

Nelu wrote:
<snip>
> --
> Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
> We must do something. This is something. Therefore, we must do this.


Sorry, I forgot to snip your signature from my previous post and paste
mine. I guess this is a sign I should go to sleep :-).


It's a sign that you should use a newsreader that does it for you <g>.

--
Al Balmer
Sun City, AZ
May 15 '06 #49

P: n/a
On Fri, 12 May 2006 20:54:13 -0400, "Rod Pemberton"
<do*********@bitfoad.cmm> wrote:

(in a reply to Richard Heathfield.)

The argument makes sense. Have you ever programmed? In C?


Heh. I suggest that you search both Google and Google Groups for
"Richard Heathfield". In quotes, to keep the hits to 50,000 or so.

You might also find his web site educational, on a much broader range
of topics.

--
Al Balmer
Sun City, AZ
May 15 '06 #50

53 Replies

This discussion thread is closed

Replies have been disabled for this discussion.