sizeof and arrays/pointers question 
Author Message
 sizeof and arrays/pointers question

Hello all...

 I am (still :-) a little confused about the sizeof() operator and
arrays and pointers.

  consider the array

 char str[10];

  normally if I refer to 'str', it 'decays' to a pointer (char *). for
example, if I do printf("%ld", str) (probably not very portable or anything :)
printf gets passed a pointer to an array. likewise, if I do

  long num = (long) str;

  then num is (attempted to be) set to the pointer to str. Thus for
the assignment operator, str decays to a pointer. However, if I do

  int num = sizeof(str);

  the sizeof operator DOES NOT make str decay to a pointer, it returns the
value 10. Exactly the same thing happens with string literals and
arrays delcared like

  char str[]="Blah"

  although not for things like

  char *str = "blah"

  obviously because str already _is_ a pointer.

  So, how come some built in operators (eg =) make str[] decay to a pointer
before they evaluate it and 'operate' on it, but some of them keep it as an
array (eg sizeof) and 'operate' on that? Isn't that a bit inconsistent?

Russell
--

 Student of Computer Science and Electrical and Computer Systems Engineering
 -\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-
            "Errr. Six Hundred and Four, Toxteth O'Grady, USA."



Thu, 27 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:
>   So, how come some built in operators (eg =) make str[] decay to a pointer
> before they evaluate it and 'operate' on it, but some of them keep it as an
> array (eg sizeof) and 'operate' on that? Isn't that a bit inconsistent?

Inconsistent, but necessary (as long as you allow array decay at all).
If sizeof allowed an array to decay, how would you get the size of one?

(If the inconsistency was to be fixed, though I hope it will not,
it should be fixed by removing array decay.)

--

NEW: Publib version 0.5: ftp://ftp.cs.helsinki.fi/pub/Software/Local/Publib/



Fri, 28 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question
|>
|>  I am (still :-) a little confused about the sizeof() operator and
|> arrays and pointers.
|>
|>   ...
|>
|>   So, how come some built in operators (eg =) make str[] decay to a pointer
|> before they evaluate it and 'operate' on it, but some of them keep it as an
|> array (eg sizeof) and 'operate' on that? Isn't that a bit inconsistent?

No, just unspeakably perverse.  K&R C was inconsistent, but ANSI C
'cleaned up' the specification.  However, the result is so bizarre
that no right-minded person would believe it without proof.  I shall
not attempt to explain what is going on, except to comment that your
model of what is going on isn't quite right.  You need to put an
ice-pack on your head, and study the actual standard, I am afraid.

Remember also that sizeof() operates on TYPES and not VALUES, unlike
any other construction in C, except possibly offsetof().

Nick Maclaren,
University of Cambridge Computer Laboratory,
New Museums Site, Pembroke Street, Cambridge CB2 3QG, England.

Tel.:  +44 1223 334761    Fax:  +44 1223 334679



Fri, 28 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:
>  So, how come some built in operators (eg =) make str[] decay to a pointer
>before they evaluate it and 'operate' on it, but some of them keep it as an
>array (eg sizeof) and 'operate' on that? Isn't that a bit inconsistent?

Arrays decay into pointers when used in a value context.  If you keep
this simple rule in mind, everything is consistent.

You can find more about this in Section 2 of the FAQ.

Dan
--
Dan Pop
CERN, CN Division

Mail:  CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland



Fri, 28 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:

>Hello all...
> I am (still :-) a little confused about the sizeof() operator and
>arrays and pointers.
>  consider the array
> char str[10];
>  normally if I refer to 'str', it 'decays' to a pointer (char *). for
>example, if I do printf("%ld", str) (probably not very portable or anything :)
>printf gets passed a pointer to an array. likewise, if I do
>  long num = (long) str;
>  then num is (attempted to be) set to the pointer to str. Thus for
>the assignment operator, str decays to a pointer. However, if I do
>  int num = sizeof(str);
>  the sizeof operator DOES NOT make str decay to a pointer, it returns the
>value 10. Exactly the same thing happens with string literals and
>arrays delcared like
>  char str[]="Blah"
>  although not for things like
>  char *str = "blah"
>  obviously because str already _is_ a pointer.
>  So, how come some built in operators (eg =) make str[] decay to a pointer
>before they evaluate it and 'operate' on it, but some of them keep it as an
>array (eg sizeof) and 'operate' on that? Isn't that a bit inconsistent?

Perhaps this confusion arises because the sizeof operator generates no
runtime code on compliant compilers.  The quantity is determined at compile
time.  Most other operators must have parameters evaluated at run-time.

Quote:
>Russell

John Powell


Fri, 28 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:
Sonnack) writes:


|>
|> >  I am (still :-) a little confused about the sizeof() operator and
|> > arrays and pointers.
|>
|> My way of looking at it is that sizeof() returns the actual amount
|> of memory allocated for the object in question. In terms of their
|> //type//, examples A and B are the same, but in terms of the amount

That is wrong, if by //type// you mean anything usual. Only the type of the
decayed value of A (e.g. the type of A+0) is the same as the type of B.
Because of the many automatic type transformations that go on in C, this is
not actually unusual: e.g. after `char x;' x has type char, but +x has type
int.

|> of allocated memory (for the variables), they are very different:
|>
|> example A:        char  A [] = "Poohbear";
|> example B:        char* B    = "Poohbear";

I tend to look upon array decay as happening in a _value_ context: i.e.
whenever a non-register lvalue array needs to be converted to an rvalue; as
opposed to when it merely refers to an object i.e. _is_ an lvalue. sizeof
gives the size of the result of an expression thought of as an object (even
if it is not an lvalue), which because of the fixed typing scheme of C is
indeed the size of the _type_ of the result of the expression which is,
therefore, not evaluated at all.  (Of course sizeof can operate directly
on a type name in parantheses as well).

The same rule shows why &A gives a result of a different type than &B above.
The operand of & is logically an lvalue (one wants the address of the object:
not of its value, surely), and so the array does not decay. The former is a
pointer to an array, the latter a pointer to a pointer.

Similar rules apply to functions: except that functions are not objects, and
so sizeof gives an error when applied to them.

Cheers
Tanmoy
--

Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87544-0285,USA H:#3,802,9 St,NM87545
Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>,
<http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/
internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html>
fax: 1 (505) 665 3003   voice: 1 (505) 665 4733    [ Home: 1 (505) 662 5596 ]



Fri, 28 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:

>  I am (still :-) a little confused about the sizeof() operator and
> arrays and pointers.

My way of looking at it is that sizeof() returns the actual amount
of memory allocated for the object in question. In terms of their
//type//, examples A and B are the same, but in terms of the amount
of allocated memory (for the variables), they are very different:

example A:      char  A [] = "Poohbear";
example B:      char* B    = "Poohbear";

The (memory use) size of A is 9 bytes; of B it's only sizeof(char*).
From: this!
Newsgroups: comp.lang.c.moderated

Both variables have the same //type//, because C treats an array
name as a 'pointer to X'. But there are subtle distinctions because
they are different things.

--
Chris Sonnack       | 3M/Information Technology/Engineering Info Svcs

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"The whole earth is in jail and we're plotting this incredible jailbreak."



Fri, 28 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:

>  So, how come some built in operators (eg =) make str[] decay to a pointer
>before they evaluate it and 'operate' on it, but some of them keep it as an
>array (eg sizeof) and 'operate' on that? Isn't that a bit inconsistent?

Consider the statement:

        int a, b;

        a = 3;
        b = a;

One can equally say:

        So, how come some built in operators (eg =) make a variable
        decay to its value before they evalute it and 'operate' on
        it, but some of them keep it as a variable?

That is, in `b = a', how come we got the *value* of `a' (the `3' from
the first assignment) and stuck it in the *object* `b'?

To anyone who has been programming for a while, the reason is obvious:
some contexts call for an object, and some call for a value.  If you
put an object where you need a value, the compiler fetches the current
value stored in the object.

What C does (which is not inconsistent, merely unusual) is to say
that the `value' of an array is the address of its first element.
Where the array has type `array N of T' (for some integer constant
N and valid element type T), the `value' of the array has type
`pointer to T'.

This does make it virtually impossible to obtain the aggregate
value of the array (the values of all the elements) for use in
function calls, return statements, and so on, which is one reason
other languages treat arrays as first-class citizens.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc



Sat, 29 Nov 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:

>>>  I am (still :-) a little confused about the sizeof() operator and
>>> arrays and pointers.

>> My way of looking at it is that sizeof() returns the actual amount
>> of memory allocated for the object in question. In terms of their
>> //type//, examples A and B are the same, but in terms of the amount

> That is wrong, if by //type// you mean anything usual. Only the type of
> the decayed value of A (e.g. the type of A+0) is the same as the type of
> B.

Huh? I don't really understand your first sentence there, but your
second one has to be in error. Here's the examples from my post:

Quote:
>> example A:     char  A [] = "Poohbear";
>> example B:     char* B    = "Poohbear";

Isn't it true that //both// A and B have the type (char*)? And isn't the
type of A+0 a (char), so how can it be the same as B? I don't follow
what you're trying to say.

I know that I can pass A or B to any function that takes a (char*). They
are //not// the same in that B may be an lvalue, A may not, and also in
the amount of memory they use.

Quote:
> Because of the many automatic type transformations that go on in C, this
> is not actually unusual: e.g. after `char x;' x has type char, but +x has
> type int.

Well, (char) is just a {*filter*}y-tiny (int), afterall. But few compilers will
sit still for an attempt to auto-convert between (int) and (int*). There
is a big difference there!

Quote:
> I tend to look upon array decay as happening in a _value_ context: i.e.
> whenever a non-register lvalue array needs to be converted to an rvalue;
> as opposed to when it merely refers to an object i.e. _is_ an lvalue.

Huh? If I could see through this opaque pedantry, I think I'd disagree.
I'm still stuck trying to imagine an IS-register lvalue array... I'm not
sure I understand the term "array decay" (an array has the type (X*)
where X is the type of the array members??).

But I do know that an array name (alone) can //never// BE an lvalue.
Does //that// have something to do with your point?

Quote:
> sizeof gives the size of the result of an expression thought of as an
> object (even if it is not an lvalue), which because of the fixed typing
> scheme of C is indeed the size of the _type_ of the result of the
> expression which is, therefore, not evaluated at all.

Well, I understand the first part, because:

        int  a=1, b=2, c=3;

        sizeof (a) == sizeof (int);
        sizeof (a+b) == sizeof (int);
        sizeof (a+b+c) == sizeof (int);

...but you lost me after the first clause. Yes, C has fixed typing, and,
yes, you get the //type// of the expression, and, yes, the expression is
not evaluated. And, so...??

Quote:
> The same rule shows why &A gives a result of a different type than &B
> above.  The operand of & is logically an lvalue (one wants the address
> of the object: not of its value, surely), and so the array does not decay.
> The former is a pointer to an array, the latter a pointer to a pointer.

Do we have different meanings for a lvalue? My understanding is that an
"lvalue" is something that can be on the "left side" of an operator. It
is something to which you can assign a value. By my understanding, A is
//not// an lvalue. Only the second example is valid:

        char  A [] = "Hello";
        char* B    = "Sailor!";

        A = "Good-Night";     /* invalid */
        B = "Irene";          /* valid   */

Of course &A and &B give different results: the former is the address
of an array of (in this case) 6 chars; the latter is the address of a
pointer to a(n array of) char(s). A & B //are// different, but I still
say that, for most uses, they have the same type.

regards,
--
Chris Sonnack       | 3M/Information Technology/Engineering Info Svcs

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"The first duty of a revolutionary is to get away with it."



Wed, 03 Dec 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:



>>  So, how come some built in operators (eg =) make str[] decay to a pointer
>>before they evaluate it and 'operate' on it, but some of them keep it as an
>>array (eg sizeof) and 'operate' on that? Isn't that a bit inconsistent?
>Consider the statement:
>    int a, b;
>    a = 3;
>    b = a;
>One can equally say:
>    So, how come some built in operators (eg =) make a variable
>    decay to its value before they evalute it and 'operate' on
>    it, but some of them keep it as a variable?

 You're absolutely right :-) I hadn't thought of that.

Quote:
>What C does (which is not inconsistent, merely unusual) is to say
>that the `value' of an array is the address of its first element.
>Where the array has type `array N of T' (for some integer constant
>N and valid element type T), the `value' of the array has type
>`pointer to T'.
>This does make it virtually impossible to obtain the aggregate
>value of the array (the values of all the elements) for use in
>function calls, return statements, and so on, which is one reason
>other languages treat arrays as first-class citizens.

   Yeah that was the conclusion I had reached. Some kind of system
where you could pass an array by value, or an pointer to an array of however
many dimensions specified in the prototype, with an internal header that
contains some internal info like the width of the rows, etc so that
both the sizeof() operator and normal indexing will work within a function
that is passed to it. (by value or simulated reference) I guess you could
do this with structs, but still, full language level support would be good.

Russell
--

 Student of Computer Science and Electrical and Computer Systems Engineering
 -\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-
            "Errr. Six Hundred and Four, Toxteth O'Grady, USA."



Wed, 03 Dec 1997 03:00:00 GMT  
 sizeof and arrays/pointers question
sizeof() is determined at compile time, not run-time.
When you say

char str_buf[]="blah"

sizeof(str_buf) will be 5, because that is the size of the array.

If you say

char *str_ptr = "blah"

sizeof(str_ptr) returns the size of a pointer.

The reason why

char *ptr;
char *buf = "blah";

ptr=buf;

is legal is because of the way computers work. This happens at run time, not
compile time. At run time, computers cannot hold arrays internal to the CPU and
access them in the way strings are frequently accessed.

Hank



Wed, 03 Dec 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:
>My way of looking at it is that sizeof() returns the actual amount
>of memory allocated for the object in question. In terms of their
>//type//, examples A and B are the same,

I disagree. The data being stored is the same but the types are
different.

Quote:
>but in terms of the amount
>of allocated memory (for the variables), they are very different:

>example A:      char  A [] = "Poohbear";
>example B:      char* B    = "Poohbear";

>The (memory use) size of A is 9 bytes; of B it's only sizeof(char*).
>From: this!
>Newsgroups: comp.lang.c.moderated

>Both variables have the same //type//, because C treats an array
>name as a 'pointer to X'.

I disagree. A programmer can use them the same sometimes, but C
treats them different.

Quote:
>But there are subtle distinctions because
>they are different things.

When an operator returns different values, I don't cosider that
subtle.

Quote:

>--
>Chris Sonnack       | 3M/Information Technology/Engineering Info Svcs


--
Harold Guller



Wed, 03 Dec 1997 03:00:00 GMT  
 sizeof and arrays/pointers question

Quote:

>Some kind of system where you could pass an array by value, or an pointer
>to an array of however many dimensions specified in the prototype, with an
>internal header that contains some internal info like the width of the rows

That's getting into PL/I and Algol68 and Ada(?) territory, but if you do
know the bounds of an array it's imo very worthwhile to specify them
wherever possible, e.g.

  char (*pbname)[32];

First, and perhaps most valuable, it highlights the array-value semantics
at every turn, and second it's potentially very useful for static checks
or really studly alias optimizations.  I do this myself, and it's caught
several buffersize mismatches that would have turned into really, really
{*filter*} bugs.

mho,
Jim
--
Jim Hill              Contents public domain and worth $.02 more than you paid.



Wed, 03 Dec 1997 03:00:00 GMT  
 sizeof and arrays/pointers question


 > sizeof() is determined at compile time, not run-time.

It is true that the semantics of sizeof mean it is always determinable at
compile time. A compiler isn't required to do this but it would be a poor
one that didn't.

 > When you say
 >
 > char str_buf[]="blah"
 >
 > sizeof(str_buf) will be 5, because that is the size of the array.

More explicitly the definition above gives str_buf type (char [5]) and
sizeof returns the size of that type.

 >
 > If you say
 >
 > char *str_ptr = "blah"
 >
 > sizeof(str_ptr) returns the size of a pointer.

Yes, here str_ptr has type (char *) and sizeof returns the size of that type.

 > The reason why
 >
 > char *ptr;
 > char *buf = "blah";
 >
 > ptr=buf;
 >
 > is legal is because of the way computers work. This happens at run time, not
 > compile time. At run time, computers cannot hold arrays internal to the CPU and
 > access them in the way strings are frequently accessed.

No, the reason is the C language definition. "The way computers work" is
not relevant (evidence being that most other languages don't work like this).
The standard says (in section 6.2.2.1):

"Except where it is the operand of the sizeof operator or the unary &
operator, or is a character string literal used to initialise an array of
character type, or is a wide string literal used to initialise an array with
element type compatible with wchar_t, an lvalue that has type ``array of
type'' is converted to an expression that has type ``pointer to
functions returning type.'' "

--
-----------------------------------------


-----------------------------------------



Thu, 04 Dec 1997 03:00:00 GMT  
 sizeof and arrays/pointers question



 >
 > >>>  I am (still :-) a little confused about the sizeof() operator and
 > >>> arrays and pointers.
 > >>
 > >> My way of looking at it is that sizeof() returns the actual amount
 > >> of memory allocated for the object in question. In terms of their
 > >> //type//, examples A and B are the same, but in terms of the amount
 > >
 > > That is wrong, if by //type// you mean anything usual. Only the type of
 > > the decayed value of A (e.g. the type of A+0) is the same as the type of
 > > B.
 >
 > Huh? I don't really understand your first sentence there, but your
 > second one has to be in error. Here's the examples from my post:

It is correct.

 > >> example A:   char  A [] = "Poohbear";
 > >> example B:   char* B    = "Poohbear";
 >
 > Isn't it true that //both// A and B have the type (char*)? And isn't the
 > type of A+0 a (char), so how can it be the same as B? I don't follow
 > what you're trying to say.

A has type (char [9])

B has type (char *)

A+0 has type (char *)

A[0], *A, B[0], and *B all have type (char)

A is not a pointer (and no pointer exists anywhere in the memory it is
stored in). However in C whenever you try to take the value of an array
the compiler gives you the address of (i.e. a pointer to) of its first
element. That is why A+0 has type (char *). Of course you have to know that
when you add an integer to a pointer you get a pointer with the same type.

 > I know that I can pass A or B to any function that takes a (char*). They
 > are //not// the same in that B may be an lvalue, A may not, and also in
 > the amount of memory they use.

When passing an array as a function argument you are trying to take its
value hence the rule above applies.

 > > Because of the many automatic type transformations that go on in C, this
 > > is not actually unusual: e.g. after `char x;' x has type char, but +x has
 > > type int.
 >
 > Well, (char) is just a {*filter*}y-tiny (int), afterall. But few compilers will
 > sit still for an attempt to auto-convert between (int) and (int*). There
 > is a big difference there!

True, but no such conversion is implied here.

 > > I tend to look upon array decay as happening in a _value_ context: i.e.
 > > whenever a non-register lvalue array needs to be converted to an rvalue;
 > > as opposed to when it merely refers to an object i.e. _is_ an lvalue.
 >
 > Huh? If I could see through this opaque pedantry, I think I'd disagree.
 > I'm still stuck trying to imagine an IS-register lvalue array... I'm not
 > sure I understand the term "array decay" (an array has the type (X*)
 > where X is the type of the array members??).

It's just another way of stating (perhaps more formally) what I said above.
Don't treat it as pedantry, it is a simple rule and when you understand
it everything clicks into place.

 > But I do know that an array name (alone) can //never// BE an lvalue.
 > Does //that// have something to do with your point?

The C standard complicated things slightly by splitting lvalue into
modifiable and non-modifiable lvalues. An array is an example of a
non-modifiable lvalue. Another example is a const variable. You might think
of an lvalue as something with storage duration i.e. can cross statement
boundaries whereas an rvalue cannot (that is maybe a somewhat curious
definition which just occurred to me, I'm sure others will consider whether
it is valid or not!)

 > > sizeof gives the size of the result of an expression thought of as an
 > > object (even if it is not an lvalue), which because of the fixed typing
 > > scheme of C is indeed the size of the _type_ of the result of the
 > > expression which is, therefore, not evaluated at all.
 >
 > Well, I understand the first part, because:
 >
 >         int  a=1, b=2, c=3;
 >
 >         sizeof (a) == sizeof (int);
 >         sizeof (a+b) == sizeof (int);
 >         sizeof (a+b+c) == sizeof (int);
 >
 > ...but you lost me after the first clause. Yes, C has fixed typing, and,
 > yes, you get the //type// of the expression, and, yes, the expression is
 > not evaluated. And, so...??

So sizeof(A+0) == sizeof(char *)

 > > The same rule shows why &A gives a result of a different type than &B
 > > above.  The operand of & is logically an lvalue (one wants the address
 > > of the object: not of its value, surely), and so the array does not decay.
 > > The former is a pointer to an array, the latter a pointer to a pointer.
 >
 > Do we have different meanings for a lvalue? My understanding is that an
 > "lvalue" is something that can be on the "left side" of an operator. It
 > is something to which you can assign a value. By my understanding, A is
 > //not// an lvalue. Only the second example is valid:

A footnote in the standard suggests you think of lvalue to mean "locator
value". There are lvalues (i.e. non-modifiable) in C which may not be used
on the LHS of an assignment operator.

 >         char  A [] = "Hello";
 >         char* B    = "Sailor!";
 >
 >         A = "Good-Night";       /* invalid */
 >         B = "Irene";            /* valid   */
 >
 > Of course &A and &B give different results: the former is the address
 > of an array of (in this case) 6 chars; the latter is the address of a
 > pointer to a(n array of) char(s).

Here A has type (char [6])  and that is the only type it has. That is why
&A gives you the address of an array with type (char (*)[6])

 > A & B //are// different, but I still
 > say that, for most uses, they have the same type.

The type of A is a property of A which is independent of its use. When you
take the value of A the compiler gives you a pointer to its first element
with type (char *) but that is no longer A. I realise this is what you're
getting at - when you take the value of either A or B you get a (char *)
value, but in over-generalising this you easily fall into the trap of
assuming pointer and array equivalence and it becomes much more difficult
to understand the cases where this falls apart.

--
-----------------------------------------


-----------------------------------------



Thu, 04 Dec 1997 03:00:00 GMT  
 
 [ 22 post ]  Go to page: [1] [2]

 Relevant Pages 

1. how to modify a pointer to an array one sizeof(int)

2. sizeof an array referenced by pointer

3. sizeof pointer to pointer

4. Dereferencing f-pointers, arrays of f-pointers, pointers to f-pointers

5. Array of pointers, pointer to array...

6. array pointer/pointer array

7. arrays pointers array of pointers

8. sizeof (pointer to array)/sizeof (p[0]) how to use ?

9. Pointer of Pointers was Pointer of arrays...

10. Pointers: return of pointer to array of pointers to main

11. question about array of pointers to chars

12. A question about arrays,pointers and structures

 

 
Powered by phpBB® Forum Software