Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Address of array && address of pointer to array

Reply
Thread Tools

Address of array && address of pointer to array

 
 
James Kuyper
Guest
Posts: n/a
 
      09-16-2011
On 09/15/2011 09:23 PM, Stanley Rice wrote:
>
> <snip>
>>>> Can we say that, two pointers must be equal if they are printed the same.

>>
>>> No.

>>
>> Yes.

> How to print the address of a pointer is implementation dependant,
> based on how to represent the pointer. Now I can understand two
> pointers point to the same memory location may print differently.
>
> But is it possible that two different pointers that point two
> different address print the same.


No, because the same character strings that are printed out when you use
printf("%p", ...) must be readable by scanf("%p", ...), and the result
of the read must be a pointer that compares equal to the original. If
two pointers that pointed at different locations caused the same string
to be printed out, then when scanned back in, the would necessarily
compare equal not only to their originals, but also to each other, since
the printed strings provide no way to distinguish them. Pointers to
different locations in memory are not allowed to compare equal, so they
must print out different character strings.

Equal pointers can print differently (though it is unlikely that they
would do so); unequal pointers MUST print differently.
--
James Kuyper
 
Reply With Quote
 
 
 
 
Nobody
Guest
Posts: n/a
 
      09-16-2011
On Thu, 15 Sep 2011 10:28:10 -0700, Keith Thompson wrote:

>> An
>> implementation is free to print e.g. "?" for every pointer.

>
> No, it isn't. The string printed by printf with "%p" must be readable
> by scanf with "%p", and the result from scanf must compare equal to the
> original pointer.


Ah. I actually checked the spec regarding printf("%p"), which doesn't say
anything useful:

p The argument shall be a pointer to void. The value
of the pointer is converted to a sequence of
printable characters, in an implementation-defined
manner.

It didn't occur to me to check scanf(), which says:

p Matches an implementation-defined set of sequences,
which should be the same as the set of sequences
that may be produced by the %p conversion of the
fprintf function. The corresponding argument shall
be a pointer to a pointer to void. The
interpretation of the input item is implementation-
defined. If the input item is a value converted
earlier during the same program execution, the
pointer that results shall compare equal to that
value; otherwise the behavior of the %p conversion
is undefined.

Which suggests that the answer to the question:

> Can we say that, two pointers must be equal if they are printed the same.


should be "yes" (subject to the proviso that comparing the pointers for
equality is actually legal).

However: I suggest that it would be legal for the implementation to print
all pointers as "?" if it can detect that the *scanf() functions aren't
used by the program.

 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      09-16-2011
Stanley Rice <(E-Mail Removed)> writes:

> On Sep 16, 3:26┬*am, pete <(E-Mail Removed)> 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.
 
Reply With Quote
 
Nobody
Guest
Posts: n/a
 
      09-16-2011
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.

 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      09-16-2011
On 09/15/2011 09:08 PM, Stanley Rice wrote:
> On Sep 16, 3:26´┐Żam, pete <(E-Mail Removed)> 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 UTF 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
 
Reply With Quote
 
Stanley Rice
Guest
Posts: n/a
 
      09-16-2011
On Sep 16, 9:18*am, James Kuyper <(E-Mail Removed)> wrote:
> On 09/15/2011 09:13 PM, Stanley Rice wrote:
>
> > On Sep 16, 2:51 am, Keith Thompson <(E-Mail Removed)> 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?

 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      09-16-2011
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
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      09-16-2011
On 09/16/2011 08:37 AM, Stanley Rice wrote:
> On Sep 16, 9:18´┐Żam, James Kuyper <(E-Mail Removed)> wrote:
>> On 09/15/2011 09:13 PM, Stanley Rice wrote:
>>
>>> On Sep 16, 2:51 am, Keith Thompson <(E-Mail Removed)> 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
 
Reply With Quote
 
Bart van Ingen Schenau
Guest
Posts: n/a
 
      09-16-2011
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

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      09-16-2011
Nobody <(E-Mail Removed)> writes:
[...]
> However: I suggest that it would be legal for the implementation to print
> all pointers as "?" if it can detect that the *scanf() functions aren't
> used by the program.


Legal, yes. Sane, no.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointer to an array vs pointer to pointer subramanian100in@yahoo.com, India C Programming 5 09-23-2011 10:28 AM
Pointer to array of array of const pointer RSL C++ 14 02-19-2010 02:06 PM
Array of pointer and pointer of array erfan C Programming 6 01-28-2008 08:55 PM
passing the address of a pointer to a func that doesnt recieve a pointer-to-a-pointer jimjim C Programming 16 03-27-2006 11:03 PM
Array of pointer Vs Pointer to Array sangeetha C Programming 9 10-09-2004 07:01 PM



Advertisments