Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #10220 > unrolled thread

Address of array && address of pointer to array

Started byStanley Rice <heconghui@gmail.com>
First post2011-09-14 06:12 -0700
Last post2011-09-16 13:20 +0100
Articles 17 on this page of 37 — 12 participants

Back to article view | Back to comp.lang.c


Contents

  Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-14 06:12 -0700
    Re: Address of array && address of pointer to array Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-14 14:41 +0100
      Re: Address of array && address of pointer to array Paul N <gw7rib@aol.com> - 2011-09-14 14:15 -0700
      Re: Address of array && address of pointer to array Peter Nilsson <airia@acay.com.au> - 2011-09-14 19:25 -0700
        Re: Address of array && address of pointer to array Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-15 10:54 +0100
          Re: Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-15 05:36 -0700
            Re: Address of array && address of pointer to array Ike Naar <ike@sverige.freeshell.org> - 2011-09-15 13:46 +0000
            Re: Address of array && address of pointer to array Nobody <nobody@nowhere.com> - 2011-09-15 14:48 +0100
              Re: Address of array && address of pointer to array Keith Thompson <kst-u@mib.org> - 2011-09-15 10:28 -0700
                Re: Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-15 18:23 -0700
                  Re: Address of array && address of pointer to array Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-16 12:58 +0100
                  Re: Address of array && address of pointer to array James Kuyper <jameskuyper@verizon.net> - 2011-09-16 08:03 -0400
                Re: Address of array && address of pointer to array Nobody <nobody@nowhere.com> - 2011-09-16 13:09 +0100
                  Re: Address of array && address of pointer to array Keith Thompson <kst-u@mib.org> - 2011-09-16 12:05 -0700
                    Re: Address of array && address of pointer to array gazelle@shell.xmission.com (Kenny McCormack) - 2011-09-16 19:35 +0000
                    Re: Address of array && address of pointer to array Peter Nilsson <airia@acay.com.au> - 2011-09-19 15:45 -0700
                      Re: Address of array && address of pointer to array Keith Thompson <kst-u@mib.org> - 2011-09-19 17:47 -0700
            Re: Address of array && address of pointer to array James Kuyper <jameskuyper@verizon.net> - 2011-09-15 10:21 -0400
      Re: Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-15 05:22 -0700
        Re: Address of array && address of pointer to array James Kuyper <jameskuyper@verizon.net> - 2011-09-15 10:23 -0400
          Re: Address of array && address of pointer to array pete <pfiland@mindspring.com> - 2011-09-15 15:26 -0400
            Re: Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-15 18:14 -0700
              Re: Address of array && address of pointer to array Keith Thompson <kst-u@mib.org> - 2011-09-16 02:09 -0700
                Re: Address of array && address of pointer to array James Kuyper <jameskuyper@verizon.net> - 2011-09-16 08:39 -0400
                Re: Address of array && address of pointer to array pete <pfiland@mindspring.com> - 2011-09-16 18:08 -0400
              Re: Address of array && address of pointer to array Bart van Ingen Schenau <bart@ingen.ddns.info> - 2011-09-16 16:38 +0200
                Re: Address of array && address of pointer to array cri@tiac.net (Richard Harter) - 2011-09-16 22:04 +0000
            Re: Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-15 18:08 -0700
              Re: Address of array && address of pointer to array Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-16 13:12 +0100
              Re: Address of array && address of pointer to array James Kuyper <jameskuyper@verizon.net> - 2011-09-16 08:30 -0400
        Re: Address of array && address of pointer to array Keith Thompson <kst-u@mib.org> - 2011-09-15 11:51 -0700
          Re: Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-15 18:13 -0700
            Re: Address of array && address of pointer to array James Kuyper <jameskuyper@verizon.net> - 2011-09-15 21:18 -0400
              Re: Address of array && address of pointer to array Stanley Rice <heconghui@gmail.com> - 2011-09-16 05:37 -0700
                Re: Address of array && address of pointer to array James Kuyper <jameskuyper@verizon.net> - 2011-09-16 09:46 -0400
                Re: Address of array && address of pointer to array Keith Thompson <kst-u@mib.org> - 2011-09-16 12:08 -0700
            Re: Address of array && address of pointer to array Nobody <nobody@nowhere.com> - 2011-09-16 13:20 +0100

Page 2 of 2 — ← Prev page 1 [2]


#10289

Frompete <pfiland@mindspring.com>
Date2011-09-15 15:26 -0400
Message-ID<4E72516D.5E80@mindspring.com>
In reply to#10284
James Kuyper wrote:
> 
> On 09/15/2011 08:22 AM, Stanley Rice wrote:

> > So What you mean is that the compiler does most of things for us? I
> > have tried to compare the address of function, say
> >
> > void foo() { }
> >
> > assert((void *)foo == (void *)&foo);
> >
> > and it passes. Is it the reason as the issue of the array talk above ?
> 
> No, the rule for arrays doesn't apply here. However, as he said above,
> there is a similar rule for functions,
> and that is what makes this code work.



That code would be fine without the casts, 

    assert(foo == &foo);

but 
the result of a pointer to a function
being cast to a pointer to an incomplete type such as (void *), 
is undefined.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#10302

FromStanley Rice <heconghui@gmail.com>
Date2011-09-15 18:14 -0700
Message-ID<fb1e1749-853e-4399-ac85-dacae2b3110f@h6g2000yqe.googlegroups.com>
In reply to#10289
On Sep 16, 3:26 am, pete <pfil...@mindspring.com> wrote:
> James Kuyper wrote:
>
> > On 09/15/2011 08:22 AM, Stanley Rice wrote:
> > > So What you mean is that the compiler does most of things for us? I
> > > have tried to compare the address of function, say
>
> > > void foo() { }
>
> > > assert((void *)foo == (void *)&foo);
>
> > > and it passes. Is it the reason as the issue of the array talk above ?
>
> > No, the rule for arrays doesn't apply here. However, as he said above,
> > there is a similar rule for functions,
> > and that is what makes this code work.
>
> That code would be fine without the casts,
>
>     assert(foo == &foo);
>
> but
> the result of a pointer to a function
> being cast to a pointer to an incomplete type such as (void *),
> is undefined.
>
> --
> pete

Err, I seems that I am just a novice and I don't fully understand the
pointer. Why should a pointer have to an object that has a specific
type, even,(void). Every code and variable and anything else just
store in the memory. Does the pointer with the specific type to point
to locate how much memory space to charge?

For example, a pointer points to type int means that 4 bytes of memory
is in the charge of the pointer, and a pointer points to type char
means that 1 byte of memory is in the charge of the pointer. In this
way, when we dereference a pointer that points to type int, we can get
a 4 byte integer, and when we dereference a pointer to char, we can
get one byte character. Is that right? And I wrote a testing program,
the snippet is as below:

int a = 48;           // 48 represents character '0' in ASCII
int *b = &a;
char *c = (char *)b;
printf("%c\n", c);      //2

The printf statement prints the character '0'. I guess the reason is
that,according to the little-endian priciple, integer 48 stores in the
side of least significant bit, but its memory address is lowest. When
I cast pointer b explicitly with (char *) to pointer c that points to
a char. The new pointer c, points to the original address where b ever
points to, but the difference is that, the pointer c that points to a
char can only in charge of one byte, that is, the lowest byte. so, '0'
is printed.

To prove my assumption, I try to change my code, In the first
statement, I change integer 48 to 304 (304 = 256 + 48), the least
sinificant byte is still hold integer 48, but the second least
significant byte hold an integer 1. In this way, the printf statement
still print character '0'.

So I guess the use of pointer pointed type is to determine how many
byte could this pointer in charge from the least significant byte. But
I don't know whether I'm right or not.

If my assumption is correct, then may be I can guess why casting a
pointer to function to void* is undefined. The pointer points to the
starting address of the function, without knowing the whole length of
the function, so the pointer doesn't know how many bytes could the
pointer in charge of, right?

[toc] | [prev] | [next] | [standalone]


#10311

FromKeith Thompson <kst-u@mib.org>
Date2011-09-16 02:09 -0700
Message-ID<lnbouk97lk.fsf@nuthaus.mib.org>
In reply to#10302
Stanley Rice <heconghui@gmail.com> writes:
> On Sep 16, 3:26 am, pete <pfil...@mindspring.com> wrote:
>> James Kuyper wrote:
>>
>> > On 09/15/2011 08:22 AM, Stanley Rice wrote:
>> > > So What you mean is that the compiler does most of things for us? I
>> > > have tried to compare the address of function, say
>>
>> > > void foo() { }
>>
>> > > assert((void *)foo == (void *)&foo);
>>
>> > > and it passes. Is it the reason as the issue of the array talk above ?
>>
>> > No, the rule for arrays doesn't apply here. However, as he said above,
>> > there is a similar rule for functions,
>> > and that is what makes this code work.
>>
>> That code would be fine without the casts,
>>
>>     assert(foo == &foo);
>>
>> but
>> the result of a pointer to a function
>> being cast to a pointer to an incomplete type such as (void *),
>> is undefined.
>>
>> --
>> pete
>
> Err, I seems that I am just a novice and I don't fully understand the
> pointer. Why should a pointer have to an object that has a specific
> type, even,(void). Every code and variable and anything else just
> store in the memory. Does the pointer with the specific type to point
> to locate how much memory space to charge?

The type of a pointer is generally a compile-time concept.  For example,
given:

    short *p1;
    double *p2;

p1 and p2 *might* have the same size and representation, but they're of
different types.  That means, among other things, that the expression
``*p1'' is of type short, the expression ``*p2'' is of type double, and
the assignment ``p1 = p2'' is invalid, since the types are incompatible.
(I'm not using the term "incompatible" quite the same way the standard
does.)

And consider a system where int and long have exactly the same size and
representation (say they're both 4 bytes).  int* and long* are still two
distinct types, and the compiler won't allow you to assign one to the
other without a cast (or at least it will warn you if you attempt to do
so).  There's more to type than size.

> For example, a pointer points to type int means that 4 bytes of memory
> is in the charge of the pointer, and a pointer points to type char
> means that 1 byte of memory is in the charge of the pointer.

Pretty much, though I'm not sure what "in the charge of" means
here.  Also, an int isn't necessarily 4 bytes, though a char is by
definition 1 byte (but a byte can be more than 8 bits).

>                                                              In this
> way, when we dereference a pointer that points to type int, we can get
> a 4 byte integer, and when we dereference a pointer to char, we can
> get one byte character. Is that right? And I wrote a testing program,
> the snippet is as below:
>
> int a = 48;           // 48 represents character '0' in ASCII

ASCII is not the only character set; this would be better written as
    int a = '0';

> int *b = &a;
> char *c = (char *)b;

This is not reliable.  It causes c to point to the first byte of a;
that's not necessarily the low-order byte.

> printf("%c\n", c);      //2

I think you meant

printf("%c\n", *c);

> The printf statement prints the character '0'. I guess the reason is
> that,according to the little-endian priciple, integer 48 stores in the
> side of least significant bit, but its memory address is lowest. When
> I cast pointer b explicitly with (char *) to pointer c that points to
> a char. The new pointer c, points to the original address where b ever
> points to, but the difference is that, the pointer c that points to a
> char can only in charge of one byte, that is, the lowest byte. so, '0'
> is printed.

Yes, but little-endianness is not a principle, it's merely an
implementation choice.

> To prove my assumption, I try to change my code, In the first
> statement, I change integer 48 to 304 (304 = 256 + 48), the least
> sinificant byte is still hold integer 48, but the second least
> significant byte hold an integer 1. In this way, the printf statement
> still print character '0'.
>
> So I guess the use of pointer pointed type is to determine how many
> byte could this pointer in charge from the least significant byte. But
> I don't know whether I'm right or not.

It's the lowest addressed byte, not necessarily the least significant
byte.

> If my assumption is correct, then may be I can guess why casting a
> pointer to function to void* is undefined. The pointer points to the
> starting address of the function, without knowing the whole length of
> the function, so the pointer doesn't know how many bytes could the
> pointer in charge of, right?

A function pointer isn't necessarily the memory address of the start
of the function.  On most systems you're likely to use, it probably
will be, but the standard doesn't guarantee it.  For example, it
could be an index into a table of all the functions in your program.
Or it could contain additional system-specific information.  (As I
recall, function pointers on the IBM AS/400 are something like
16 bytes, though it's very likely I've got the details wrong.)
The standard only requires that function pointers work the way
they're supposed to: you can call functions through them, distinct
functions have distinct addresses, and so on.

Conversion from a function pointer to void* is undefined simply
because the standard doesn't define it -- and the reason for that
is that any definition could make a correct implementation difficult
or impossible on some systems.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#10323

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-09-16 08:39 -0400
Message-ID<j4vg1t$d3i$1@dont-email.me>
In reply to#10311
On 09/16/2011 05:09 AM, Keith Thompson wrote:
...
> A function pointer isn't necessarily the memory address of the start
> of the function.  On most systems you're likely to use, it probably
> will be, but the standard doesn't guarantee it.  For example, it
> could be an index into a table of all the functions in your program.
> Or it could contain additional system-specific information.  (As I
> recall, function pointers on the IBM AS/400 are something like
> 16 bytes, though it's very likely I've got the details wrong.)

Another alternative that I've seen, which you didn't mention, is that
the instruction in the program which should be executed first might be
different from the instruction in the program with the lowest memory
address. At some point during the function call the function might jump
back to a position lower in memory than the initial instruction. I don't
know why the compiler where I saw this happen organized the code that
way, but I gather that this particular compiler did so routinely; it
wasn't just a bizarre consequence of a particular optimization strategy.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#10357

Frompete <pfiland@mindspring.com>
Date2011-09-16 18:08 -0400
Message-ID<4E73C8C7.193A@mindspring.com>
In reply to#10311
Keith Thompson wrote:
> 
> Stanley Rice <heconghui@gmail.com> writes:
 
> > For example, a pointer points to type int
> > means that 4 bytes of memory
> > is in the charge of the pointer, and a pointer points to type char
> > means that 1 byte of memory is in the charge of the pointer.
> 
> Pretty much, though I'm not sure what "in the charge of" means
> here.  

ITHM "pointed to by"

-- 
pete

[toc] | [prev] | [next] | [standalone]


#10329

FromBart van Ingen Schenau <bart@ingen.ddns.info>
Date2011-09-16 16:38 +0200
Message-ID<j4vn1b$poc$1@localhost.localdomain>
In reply to#10302
Stanley Rice Wrote:

> 
> Err, I seems that I am just a novice and I don't fully understand
> the pointer. Why should a pointer have to an object that has a
> specific type, even,(void). Every code and variable and anything else
> just store in the memory. Does the pointer with the specific type to
> point to locate how much memory space to charge?

It might be true for the computer that you are sitting at that everything is
stored in a single big pool of memory, but C is defined to be flexible
enough that it also can deal with really weird systems.
It is, for example, possible to use C on a system with these
characteristics:
- code and data are stored in physically different areas of memory.
- code memory has 2^48 locations where functions can be located. (^ used in
the meaning of 'power of')
- data memory has 2^16 16-bit wide cells.
- the C compiler provides byte (octet) access through emulation.
On this system, you would have:
* CHAR_BITS == 8
* sizeof(char) == 1
* sizeof(short) == sizeof(int) == 2
* sizeof(long) == 4
* sizeof(void*) == sizeof(char*) == 4
* sizeof(int*) == 2
* sizeof(void (*)() /* function pointer */) == 6

As you can see, the size of the pointers themselves is not always the same
and depends on the type of data that the pointer points at.
In this case, void* and char* need to be larger to store the additional
information which portion of a memory-cell the pointer refers to.

> 
> For example, a pointer points to type int means that 4 bytes of
> memory is in the charge of the pointer, and a pointer points to type
> char means that 1 byte of memory is in the charge of the pointer. In
> this way, when we dereference a pointer that points to type int,
> we can get a 4 byte integer, and when we dereference a pointer
> to char, we can get one byte character. Is that right? And I wrote
> a testing program, the snippet is as below:
> 
> int a = 48;           // 48 represents character '0' in ASCII
> int *b = &a;
> char *c = (char *)b;
> printf("%c\n", c);      //2
> 
> The printf statement prints the character '0'. I guess the reason is
> that,according to the little-endian priciple, integer 48 stores in the
> side of least significant bit, but its memory address is lowest.

This may happen to be true for your computer, but it is not universally
true. It is equally well possible that the processor uses big-endian storage
and the integer 48 is stored in the higest byte of the memory used by the
variable a.
In that case, the printf would have resulted in the character '\0' (which is
typically invisible).

<snip> 

> So I guess the use of pointer pointed type is to determine how
> many byte could this pointer in charge from the least significant byte.
> But I don't know whether I'm right or not.

You are partially right. Another very important use of the pointed-to type
is to determine how to interpret those bytes and which operations you can
perform on them.

> 
> If my assumption is correct, then may be I can guess why casting
> a pointer to function to void* is undefined. The pointer points to
> the starting address of the function, without knowing the whole
> length of the function, so the pointer doesn't know how many
> bytes could the pointer in charge of, right?

No. The size of the function is not a concern, because a void* is also in
charge of an unspecified number of bytes.
The reason lies in the support for architectures with separate code and data
memories, where you can have more functions than data items, or where a
function pointer needs additional information (for example security
attributes) that are not needed for data pointers.

Bart v Ingen Schenau

[toc] | [prev] | [next] | [standalone]


#10356

Fromcri@tiac.net (Richard Harter)
Date2011-09-16 22:04 +0000
Message-ID<4e73c735.105006098@text.giganews.com>
In reply to#10329
On Fri, 16 Sep 2011 16:38:35 +0200, Bart van Ingen Schenau
<bart@ingen.ddns.info> wrote:

>Stanley Rice Wrote:
>
>> 
>> Err, I seems that I am just a novice and I don't fully understand
>> the pointer. Why should a pointer have to an object that has a
>> specific type, even,(void). Every code and variable and anything else
>> just store in the memory. Does the pointer with the specific type to
>> point to locate how much memory space to charge?
>
>It might be true for the computer that you are sitting at that everything is
>stored in a single big pool of memory, but C is defined to be flexible
>enough that it also can deal with really weird systems.

[snip]

Back in the bad old days the Primos C compiler had 32 bit pointers for
short/int/long and 48 bit pointers for char.  Porting to Primos was an
occasion for learning that the whole world isn't 32 bit.

[toc] | [prev] | [next] | [standalone]


#10307

FromStanley Rice <heconghui@gmail.com>
Date2011-09-15 18:08 -0700
Message-ID<b9e0b73d-8a63-4532-b724-5462796c351b@k15g2000yqd.googlegroups.com>
In reply to#10289
On Sep 16, 3:26 am, pete <pfil...@mindspring.com> wrote:
> James Kuyper wrote:
>
> > On 09/15/2011 08:22 AM, Stanley Rice wrote:
> > > So What you mean is that the compiler does most of things for us? I
> > > have tried to compare the address of function, say
>
> > > void foo() { }
>
> > > assert((void *)foo == (void *)&foo);
>
> > > and it passes. Is it the reason as the issue of the array talk above ?
>
> > No, the rule for arrays doesn't apply here. However, as he said above,
> > there is a similar rule for functions,
> > and that is what makes this code work.
>
> That code would be fine without the casts,
>
>     assert(foo == &foo);
>
> but
> the result of a pointer to a function
> being cast to a pointer to an incomplete type such as (void *),
> is undefined.
>
> --
> pete

Err, I seems that I am just a novice and I don't fully understand the
pointer. Why should a pointer have to an object that has a specific
type, even,(void). Every code and variable and anything else just
store in the memory. Does the pointer with the specific type to point
to locate how much memory space to charge?

For example, a pointer points to type int means that 4 bytes of memory
is in the charge of the pointer, and a pointer points to type char
means that 1 byte of memory is in the charge of the pointer. In this
way, when we dereference a pointer that points to type int, we can get
a 4 byte integer, and when we dereference a pointer to char, we can
get one byte character. Is that right? And I wrote a testing program,
the snippet is as below:

int a = 48;           // 48 represents character '0' in ASCII
int *b = &a;
char *c = (char *)b;
printf("%c\n", c);      //2

The printf statement prints the character '0'. I guess the reason is
that,according to the little-endian priciple, integer 48 stores in the
side of least significant bit, but its memory address is lowest. When
I cast pointer b explicitly with (char *) to pointer c that points to
a char. The new pointer c, points to the original address where b ever
points to, but the difference is that, the pointer c that points to a
char can only in charge of one byte, that is, the lowest byte. so, '0'
is printed.

To prove my assumption, I try to change my code, In the first
statement, I change integer 48 to 304 (304 = 256 + 48), the least
sinificant byte is still hold integer 48, but the second least
significant byte hold an integer 1. In this way, the printf statement
still print character '0'.

So I guess the use of pointer pointed type is to determine how many
byte could this pointer in charge from the least significant byte. But
I don't know whether I'm right or not.

If my assumption is correct, then may be I can guess why casting a
pointer to function to void* is undefined. The pointer points to the
starting address of the function, without knowing the whole length of
the function, so the pointer doesn't know how many bytes could the
pointer in charge of, right?

[toc] | [prev] | [next] | [standalone]


#10318

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-09-16 13:12 +0100
Message-ID<0.8a578443ad2081ee75de.20110916131203BST.87fwjwy9d8.fsf@bsb.me.uk>
In reply to#10307
Stanley Rice <heconghui@gmail.com> writes:

> On Sep 16, 3:26 am, pete <pfil...@mindspring.com> wrote:
>> James Kuyper wrote:
>>
>> > On 09/15/2011 08:22 AM, Stanley Rice wrote:
>> > > So What you mean is that the compiler does most of things for us? I
>> > > have tried to compare the address of function, say
>>
>> > > void foo() { }
>>
>> > > assert((void *)foo == (void *)&foo);
>>
>> > > and it passes. Is it the reason as the issue of the array talk above ?
>>
>> > No, the rule for arrays doesn't apply here. However, as he said above,
>> > there is a similar rule for functions,
>> > and that is what makes this code work.
>>
>> That code would be fine without the casts,
>>
>>     assert(foo == &foo);
>>
>> but
>> the result of a pointer to a function
>> being cast to a pointer to an incomplete type such as (void *),
>> is undefined.
>>
>> --
>> pete

It's helpful to snip sig blocks, even short ones.  I try to cut down
what I quote to a bare minimum so that posts a re short but still have
what is needed to establish the context.

> Err, I seems that I am just a novice and I don't fully understand the
> pointer. Why should a pointer have to an object that has a specific
> type, even,(void). Every code and variable and anything else just
> store in the memory. Does the pointer with the specific type to point
> to locate how much memory space to charge?

I think you are confusing pointers and addresses.  An address is a
machine concept and a pointer is a C language concept.  They are, of
course, closely related, but a pointer includes a type and that
determines what you can and can't do.  For example,

  int a = 42;
  int *ip = &a;
  void *vp = ip;

both ip and vp refer to the same place -- in some sense that represent
the same machine address; but:

 (a) You can write *ip but you can't write *vp.
 (b) You can write char *cp = vp; but you can't write char *cp = ip;
     (note that there are no casts here).
 (c) ip + 1 is a perfectly valid pointer but vp + 1 is not permitted.
 (d) Neither *(ip + 1) nor *(vp + 1) is permitted though for different
     reasons.
 (e) ip + 2 is *not* a valid pointer.  Neither is ip - 1.

These restrictions come from the C language.  If you think of pointers
as machine addresses on some system or other the restrictions probably
don't make much sense, but they are there because pointers offer an
abstract view of addresses that must work on all kinds of hardware.

<snip>
I found it hard to follow the rest.  I'm sorry about that.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#10322

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-09-16 08:30 -0400
Message-ID<j4vfhl$a0t$1@dont-email.me>
In reply to#10307
On 09/15/2011 09:08 PM, Stanley Rice wrote:
> On Sep 16, 3:26�am, pete <pfil...@mindspring.com> wrote:
>> James Kuyper wrote:
>>
>>> On 09/15/2011 08:22 AM, Stanley Rice wrote:
>>>> So What you mean is that the compiler does most of things for us? I
>>>> have tried to compare the address of function, say
>>
>>>> void foo() { }
>>
>>>> assert((void *)foo == (void *)&foo);
>>
>>>> and it passes. Is it the reason as the issue of the array talk above ?
>>
>>> No, the rule for arrays doesn't apply here. However, as he said above,
>>> there is a similar rule for functions,
>>> and that is what makes this code work.
>>
>> That code would be fine without the casts,
>>
>> � � assert(foo == &foo);
>>
>> but
>> the result of a pointer to a function
>> being cast to a pointer to an incomplete type such as (void *),
>> is undefined.

Pete is right, and I apologize for not noticing that problem and
commenting on it in my own message.

...
> Err, I seems that I am just a novice and I don't fully understand the
> pointer. Why should a pointer have to an object that has a specific
> type, even,(void). Every code and variable and anything else just
> store in the memory. Does the pointer with the specific type to point
> to locate how much memory space to charge?

A fully conforming implementation of C could store type information
inside of a pointer, but most do not. For a typical C implementation,
the type that a pointer points at is something that is implicit in the
machine code generated by your program, rather than stored in the
pointer itself, so that is not the issue.

The most common context where function pointers are incompatible with
void* pointers is machines where executable code resides in a different
memory space from the data. I've worked on machines where the compilers
could be put into a mode where data addresses were only 16 bits, while
function addresses had 32 bits. I wouldn't be surprised (and none of my
programs would fail) if, on a more modern system, data addresses had 32
bits, while function addresses had 64. That's because I never write code
that tries to stuff a function pointer into a void* pointer - there
might not be enough room for it to do so.

> For example, a pointer points to type int means that 4 bytes of memory
> is in the charge of the pointer, and a pointer points to type char
> means that 1 byte of memory is in the charge of the pointer. In this
> way, when we dereference a pointer that points to type int, we can get
> a 4 byte integer, and when we dereference a pointer to char, we can
> get one byte character. Is that right? And I wrote a testing program,
> the snippet is as below:
> 
> int a = 48;           // 48 represents character '0' in ASCII

It's better to write

	int a = '0';

This has the minor advantage of making your code portable to systems
that don't use ASCII. That's only a minor advantage, despite the fact
that ASCII is becoming less common, because most of the popular
alternatives to ASCII (such as UTF8) use the same values as ASCII for
the basic C character set.

The major advantage of using '0' rather than 48 is that it makes it very
much clearer what you are trying to do.

> int *b = &a;
> char *c = (char *)b;

This is legal; it leaves c pointing at the first byte of 'a'. That byte
might or might not have a value of 48, depending upon whether int is
bigendian or little-endian.

> printf("%c\n", c);      //2

The variable 'c' is a pointer; the "%c" format specifier requires that
the corresponding argument have a type that promotes to 'int', and
"char*" is NOT such a type. The behavior of your program is undefined.

> The printf statement prints the character '0'.

Because the behavior is undefined, it's possible that this is what your
program actually printed out, but I think that is extremely unlikely. I
suspect that the code which you actually executed may have looked like this:

	printf("%c\n", *c);

> If my assumption is correct, then may be I can guess why casting a
> pointer to function to void* is undefined. The pointer points to the
> starting address of the function, without knowing the whole length of
> the function, so the pointer doesn't know how many bytes could the
> pointer in charge of, right?

No, not really. A function pointer doesn't need to know how long the
function is. It typically encodes a location in memory at which the
first instruction implementing the function is located. Calling the
function involves a jump to that location, after which instructions are
executed in order, one after another, until sooner or later an
instruction is executed that cause either the function to return or the
program to exit.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#10287

FromKeith Thompson <kst-u@mib.org>
Date2011-09-15 11:51 -0700
Message-ID<lnvcst8wqv.fsf@nuthaus.mib.org>
In reply to#10278
Stanley Rice <heconghui@gmail.com> writes:
[...]
> So What you mean is that the compiler does most of things for us? I
> have tried to compare the address of function, say
>
> void foo() { }
>
> assert((void *)foo == (void *)&foo);
>
> and it passes. Is it the reason as the issue of the array talk above ?

That's not guaranteed to work.  The behavior of converting a function
pointer to void* is not defined.

It's likely to work in practice (and I think POSIX requires it
to work), but there have been systems where function pointers are
bigger than void*, so the conversion could lose information.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#10301

FromStanley Rice <heconghui@gmail.com>
Date2011-09-15 18:13 -0700
Message-ID<3f7eeae9-902e-4d07-865a-9045fdc9159b@hg2g2000vbb.googlegroups.com>
In reply to#10287
On Sep 16, 2:51 am, Keith Thompson <ks...@mib.org> wrote:
> Stanley Rice <hecong...@gmail.com> writes:
>
> [...]
>
> > So What you mean is that the compiler does most of things for us? I
> > have tried to compare the address of function, say
>
> > void foo() { }
>
> > assert((void *)foo == (void *)&foo);
>
> > and it passes. Is it the reason as the issue of the array talk above ?
>
> That's not guaranteed to work.  The behavior of converting a function
> pointer to void* is not defined.


<snip>
> It's likely to work in practice (and I think POSIX requires it
> to work), but there have been systems where function pointers are
> bigger than void*, so the conversion could lose information.

I am not fully understand your meaning of "function pointers are
bigger than void *". I know it's not the size of the pointer. Do you
mean that how many bytes the pointer can in charge of? i.e. a pointer
points to int can in charge of 4 bytes and a pointer points to double
can in charge of 8 bytes, where a pointer to void can only in charge
of 1 byte.


[toc] | [prev] | [next] | [standalone]


#10303

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-09-15 21:18 -0400
Message-ID<j4u84q$v90$1@dont-email.me>
In reply to#10301
On 09/15/2011 09:13 PM, Stanley Rice wrote:
> On Sep 16, 2:51�am, Keith Thompson <ks...@mib.org> wrote:
...
>> It's likely to work in practice (and I think POSIX requires it
>> to work), but there have been systems where function pointers are
>> bigger than void*, so the conversion could lose information.
> 
> I am not fully understand your meaning of "function pointers are
> bigger than void *". I know it's not the size of the pointer.

You "know" incorrectly. Function pointers can have a size that is
different from the size of void*, and there have been many systems where
this is indeed the case.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#10324

FromStanley Rice <heconghui@gmail.com>
Date2011-09-16 05:37 -0700
Message-ID<9fc229b8-6e08-4333-9aec-9e9ae22c9100@eb1g2000vbb.googlegroups.com>
In reply to#10303
On Sep 16, 9:18 am, James Kuyper <jameskuy...@verizon.net> wrote:
> On 09/15/2011 09:13 PM, Stanley Rice wrote:
>
> > On Sep 16, 2:51 am, Keith Thompson <ks...@mib.org> wrote:
> ...
> >> It's likely to work in practice (and I think POSIX requires it
> >> to work), but there have been systems where function pointers are
> >> bigger than void*, so the conversion could lose information.
>
> > I am not fully understand your meaning of "function pointers are
> > bigger than void *". I know it's not the size of the pointer.
>
> You "know" incorrectly. Function pointers can have a size that is
> different from the size of void*, and there have been many systems where
> this is indeed the case.
> --
> James Kuyper

But I try to print sizeof(void *) and sizeof(ptr2fun), supposing that
ptr2fun
is a function pointer. It generate the same result, both are 4. So is
your
meaning that in some special cases, the size of function pointer and
the
pointer to void * is different? And could you explain to me when it
occurs?

[toc] | [prev] | [next] | [standalone]


#10325

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-09-16 09:46 -0400
Message-ID<j4vk01$7op$1@dont-email.me>
In reply to#10324
On 09/16/2011 08:37 AM, Stanley Rice wrote:
> On Sep 16, 9:18�am, James Kuyper <jameskuy...@verizon.net> wrote:
>> On 09/15/2011 09:13 PM, Stanley Rice wrote:
>>
>>> On Sep 16, 2:51 am, Keith Thompson <ks...@mib.org> wrote:
>> ...
>>>> It's likely to work in practice (and I think POSIX requires it
>>>> to work), but there have been systems where function pointers are
>>>> bigger than void*, so the conversion could lose information.
>>
>>> I am not fully understand your meaning of "function pointers are
>>> bigger than void *". I know it's not the size of the pointer.
>>
>> You "know" incorrectly. Function pointers can have a size that is
>> different from the size of void*, and there have been many systems where
>> this is indeed the case.
>> --
>> James Kuyper
> 
> But I try to print sizeof(void *) and sizeof(ptr2fun), supposing that
> ptr2fun
> is a function pointer. It generate the same result, both are 4. So is
> your
> meaning that in some special cases, the size of function pointer and
> the
> pointer to void * is different? And could you explain to me when it
> occurs?

The size of the void* and the size of a given function pointer type are
both implementation-specific, and there's no requirement that they be
the same. On a different implementation, they might be different, and
either one might be larger than the other.

There's only a few cases where the standard imposes any size
requirements. Note that, in C, a byte contains CHAR_BIT bits, and
CHAR_BIT is allowed to be greater than 8. (5.2.4.2.1p1).

The minimum required range of the basic integer type implies a minimum
number of bits needed to store each type (5.2.4.2.1p1):
	short, int: 16 bits
	long: 32 bits
	long long: 64 bits

char and signed char have the same size. (6.2.5p5)

For every signed integer type, the corresponding unsigned integer type
must have the same size. (6.2.5p6)

float _Complex is required to have the same size as float[2]; similarly
for double and long double. (6.2.5p13)

For any given type T:
const T, volatile T, and const volatile T are all required to have the
same size. (6.2.5p26)

For any given pair of compatible types T and U (including T==U as a
special case),
T*, const T*, volatile T*, and const volatile T*, U*, const U*, volatile
U*, and const volatile U* are all required to have the same size. (6.2.5p27)

char*, signed char*, unsigned char*, and void* are all required to have
the same size. (6.2.5p27)

All pointers to structure types have the same size. (6.2.5p27)

All pointers to union types have the same size. (6.2.5p27)

Pointers to other types need NOT have the same size (6.2.5p27)

char, signed char, and unsigned char all have a size of 1 byte (6.5.3.4p3).

The exact-width types, [u]intN_t, take up exactly N bits of memory.
(7.18.1.1p2)
The minimum-width and fastest minimum-width types, [u]int_leastN_t
(7.18.1.2p2) and [u]int_fastN_t (7.18.1.3p2), take up at least N bits of
memory, but possibly more.

The minimum required ranges of certain other types imply a minimum
number of bits (7.18.2.4p1):
	sig_atomic_t, wchar_t: 8 bits
	inptr_t, uintptr_t, ptrdiff_t, size_t, wint_t: 16 bits

float _Imaginary is required to have same size as float; similarly for
double and long double. (Annex Gp4)

For any types not listed above, you should avoid making any assumptions
about their sizes.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#10341

FromKeith Thompson <kst-u@mib.org>
Date2011-09-16 12:08 -0700
Message-ID<ln39fw8fvr.fsf@nuthaus.mib.org>
In reply to#10324
Stanley Rice <heconghui@gmail.com> writes:
> On Sep 16, 9:18 am, James Kuyper <jameskuy...@verizon.net> wrote:
>> On 09/15/2011 09:13 PM, Stanley Rice wrote:
>> > On Sep 16, 2:51 am, Keith Thompson <ks...@mib.org> wrote:
>> ...
>> >> It's likely to work in practice (and I think POSIX requires it
>> >> to work), but there have been systems where function pointers are
>> >> bigger than void*, so the conversion could lose information.
>>
>> > I am not fully understand your meaning of "function pointers are
>> > bigger than void *". I know it's not the size of the pointer.
>>
>> You "know" incorrectly. Function pointers can have a size that is
>> different from the size of void*, and there have been many systems where
>> this is indeed the case.
>> --
>> James Kuyper
>
> But I try to print sizeof(void *) and sizeof(ptr2fun), supposing that
> ptr2fun is a function pointer. It generate the same result, both are
> 4. So is your meaning that in some special cases, the size of function
> pointer and the pointer to void * is different? And could you explain
> to me when it occurs?

You've demonstrated that void* and ptr2fun have the same size *under
your implementation*.  That says nothing about other implementations,
or about what the language standard requires.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#10320

FromNobody <nobody@nowhere.com>
Date2011-09-16 13:20 +0100
Message-ID<pan.2011.09.16.12.20.48.30000@nowhere.com>
In reply to#10301
On Thu, 15 Sep 2011 18:13:59 -0700, Stanley Rice wrote:

>> That's not guaranteed to work.  The behavior of converting a function
>> pointer to void* is not defined.
> 
> 
> <snip>
>> It's likely to work in practice (and I think POSIX requires it
>> to work), but there have been systems where function pointers are
>> bigger than void*, so the conversion could lose information.
> 
> I am not fully understand your meaning of "function pointers are
> bigger than void *". I know it's not the size of the pointer.

No, he means the size of the pointer itself.

Pointers don't have to all have the same size. The most common
counter-example is 8086 memory models.

The "medium" model has multiple code segements but a single data segment,
so a function pointer is 32 bits (segment + offset) while a data pointer
(including "void*") is 16 bits (offset only).

The "compact" model is the other way around (a single code segment but
multiple data segments).

A less common counter-example is word-addressed architectures, where a
pointer to a type smaller than a word must contain both the address of the
word and an offset within the word. Pointers to types as large as or
larger than a word don't require the offset.

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c


csiph-web