pointers and integers

J

junky_fellow

I have a question related to pointer/integer conversion.
After reading various threads on this newsgroup I found that
pointer/integer conversion is not portable and may lead to
undefined results even on the same platform. I was just curious
to know why is it so ? One obvious reason is that size of
pointer variable might not be the same as integer variable.
What could be the other reasons ?

Consider an implementation where pointers and integer variables
are all of *same* size (say 4 bytes).
On such a platform, can the integer/pointer conversion cause
any undefined results ? Why ?
For eg. Consider the following piece of code:

int main (void)
{
int * ptr_i ;
int value = 0x100; /* I want to access location 0x100 in
memory */

ptr_i = value;
}

Assume sizeof(int *) is equal to sizeof(int).
What sort of problems could the "ptr_i = value" may lead to ?
After the conversion of "value" to "ptr_i", is it possible
that "ptr_i" contain altogether a different value ?
 
E

EventHelix.com

When the pointer and the integer are of the same size you
should be able to convert a pointer to an integer without
any problem.

However it is not a recommended practice due to
portability, code readability and reliability concerns.
 
P

pete

I have a question related to pointer/integer conversion.
After reading various threads on this newsgroup I found that
pointer/integer conversion is not portable and may lead to
undefined results even on the same platform. I was just curious
to know why is it so ? One obvious reason is that size of
pointer variable might not be the same as integer variable.
What could be the other reasons ?

Consider an implementation where pointers and integer variables
are all of *same* size (say 4 bytes).
On such a platform, can the integer/pointer conversion cause
any undefined results ? Why ?
For eg. Consider the following piece of code:

int main (void)
{
int * ptr_i ;
int value = 0x100; /* I want to access location 0x100 in
memory */

ptr_i = value;
}

If you know that you want to access location 0x100 in memory,
then you're not dealing with a portable code situation,
so why worry about portability of such code?
 
R

Richard Bos

EventHelix.com said:
When the pointer and the integer are of the same size you
should be able to convert a pointer to an integer without
any problem.

Wrong. RTBS.

You can always _cast_ any integer to any kind of pointer, regardless of
their sizes. However, the result need not even be a valid pointer value,
so you can't rely on being able to use it for anything; even assignment
to a pointer variable can cause undefined behaviour.

The only exception is the obvious one: a null pointer constant.

Richard
 
R

Richard Bos

int main (void)
{
int * ptr_i ;
int value = 0x100; /* I want to access location 0x100 in
memory */

ptr_i = value;
}

Assume sizeof(int *) is equal to sizeof(int).

The assumption is irrelevant. This code is not correct no matter what
sizes the types have. Correct the last line to

ptr_i = (int *)value;

and it's at least syntactically OK.
You still have the problem that you can't know that there even is memory
at "0x100". What if you've been given the block of memory ranging from
344a:1000 - 344a:8fff, and the memory from 3b00:0300 - 3b00:ffff?
Whatever address would "0x100" refer to then?

Richard
 
J

junky_fellow

Richard said:
The assumption is irrelevant. This code is not correct no matter what
sizes the types have. Correct the last line to

ptr_i = (int *)value;

and it's at least syntactically OK.
You still have the problem that you can't know that there even is memory
at "0x100". What if you've been given the block of memory ranging from
344a:1000 - 344a:8fff, and the memory from 3b00:0300 - 3b00:ffff?
Whatever address would "0x100" refer to then?

Richard

I took 0x100 just for an example. In embedded systems, sometimes many
registers are memory mapped and to access these regsiters you may need
to do this kind of assignment.
 
J

junky_fellow

Richard said:
Wrong. RTBS.

You can always _cast_ any integer to any kind of pointer, regardless of
their sizes. However, the result need not even be a valid pointer value,
so you can't rely on being able to use it for anything; even assignment
to a pointer variable can cause undefined behaviour.

The only exception is the obvious one: a null pointer constant.

Richard

You are right that an integer can be converted to any kind of pointer.
Does that mean that the size of pointer variable would always be
greater than or equal to the integer variable ?

During integer to pointer conversion, can the compiler set/reset some
of the bits, so that the value stored in pointer variable is altogether
different from original integer value ? For eg. if the integer variable
contains some value which is not word aligned and in the implementation
the integer pointer has to be word aligned, then can the compiler
store the aligned value in the pointer variable ?
 
P

pete

I took 0x100 just for an example. In embedded systems, sometimes many
registers are memory mapped and to access these regsiters you may need
to do this kind of assignment.

For an embedded system like that,
you should read your compiler's documentation
to find out how it deals with integer to pointer conversions.
 
R

Richard Bos

You are right that an integer can be converted to any kind of pointer.
Does that mean that the size of pointer variable would always be
greater than or equal to the integer variable ?

No; why should it? I never wrote that all integers can be converted to
_different_ pointers, or that all pointers values can be created by
conversion from integers. You can cast integers to pointers; the results
you get are completely system-dependent. It isn't even guaranteed that
the result is valid.
During integer to pointer conversion, can the compiler set/reset some
of the bits,

It is not a bitwise operation; conversions work by value, not by
representation.

Richard
 
G

Gordon Burditt

int value = 0x100; /* I want to access location 0x100 in
memory */

This want is an inherently unportable want, especially on systems
where addresses always have colons in them. It is also likely to
be nonsensical where all program-accessable memory uses virtual
addresses and there *IS NO* value you can stuff into a pointer to
get to the physical address you want.

If you are doing embedded code and you know for sure what "memory
location 0x100" is, throw portability out the window and go ahead
and use it. You probably need to look at the kind of code your
compiler generates in assembly language. You might have to translate
that address to 0x0010:0x0000, though, on an *86 platform, and then
to 0x00100000. Writing platform-specific code is not a sin. However,
you should be aware that what you are doing *IS* platform-specific,
and for code reusability and porting, try to separate out the
unportable stuff. And don't come crying to the compiler vendor
when something doesn't work like you thought it would.

Gordon L. Burditt
 
J

John Devereux

This want is an inherently unportable want, especially on systems
where addresses always have colons in them. It is also likely to
be nonsensical where all program-accessable memory uses virtual
addresses and there *IS NO* value you can stuff into a pointer to
get to the physical address you want.

If you are doing embedded code and you know for sure what "memory
location 0x100" is, throw portability out the window and go ahead
and use it. You probably need to look at the kind of code your
compiler generates in assembly language. You might have to translate
that address to 0x0010:0x0000, though, on an *86 platform, and then
to 0x00100000. Writing platform-specific code is not a sin. However,
you should be aware that what you are doing *IS* platform-specific,
and for code reusability and porting, try to separate out the
unportable stuff. And don't come crying to the compiler vendor
when something doesn't work like you thought it would.

It can still be possible to write code that, while "platform
dependent", is nevertheless **for that platform** portable between
various compilers and compiler command line switches.

An example would be to avoid using bit-fields to map device register
contents.
 
C

Christian Bau

I have a question related to pointer/integer conversion.
After reading various threads on this newsgroup I found that
pointer/integer conversion is not portable and may lead to
undefined results even on the same platform. I was just curious
to know why is it so ? One obvious reason is that size of
pointer variable might not be the same as integer variable.
What could be the other reasons ?

Consider an implementation where pointers and integer variables
are all of *same* size (say 4 bytes).
On such a platform, can the integer/pointer conversion cause
any undefined results ? Why ?
For eg. Consider the following piece of code:

int main (void)
{
int * ptr_i ;
int value = 0x100; /* I want to access location 0x100 in
memory */

ptr_i = value;
}

Assume sizeof(int *) is equal to sizeof(int).
What sort of problems could the "ptr_i = value" may lead to ?
After the conversion of "value" to "ptr_i", is it possible
that "ptr_i" contain altogether a different value ?

First, pointers and integers are different things. They are absolutely,
completely different things. Programmers using different languages than
C wouldn't even start thinking that pointers and integers could be
related in any way. If i change your example to:

int * ptr_i;
float value = 3.14159e2;
ptr_i = (int *) value;

would you think that there is any reason for the compiler to accept this
code, and do anything useful with it? So why do you think that casting
an integer to a pointer might do anything useful?

On an x86 processor in 16 bit mode that defines int = 32 bit, your code
above could easily produce a pointer to (segment 100, offset 0) which is
definitely not what you wanted. An x86 processor in 32 bit mode can be
set up so that only odd pointers are properly aligned and (int *) 100
isn't. I would guess that a 64 bit x86 processor can be set up so that
address 100 is not correctly aligned for 64 bit access, and there is no
reason why int shouldn't be 64 bit on such a machine. Same on a PowerPC
in 64 bit mode.

The question is not: Why should this not work? The question is: Why
would anyone think it might work?
 
C

CBFalconer

Christian said:
.... snip ...

The question is not: Why should this not work? The question is:
Why would anyone think it might work?

There is no requirement in the standard for it to work, therefore
the implementor is free to do whatever he wishes. The recent
mudslides and house destruction in California were caused by
casting an integer to a pointer in a DS9000, and attempting to
dereference it.
 
J

junky_fellow

Christian said:
First, pointers and integers are different things. They are absolutely,
completely different things. Programmers using different languages than
C wouldn't even start thinking that pointers and integers could be
related in any way. If i change your example to:

int * ptr_i;
float value = 3.14159e2;
ptr_i = (int *) value;

would you think that there is any reason for the compiler to accept this
code, and do anything useful with it? So why do you think that casting
an integer to a pointer might do anything useful?

On an x86 processor in 16 bit mode that defines int = 32 bit, your code
above could easily produce a pointer to (segment 100, offset 0) which is
definitely not what you wanted. An x86 processor in 32 bit mode can be
set up so that only odd pointers are properly aligned and (int *) 100
isn't. I would guess that a 64 bit x86 processor can be set up so that
address 100 is not correctly aligned for 64 bit access, and there is no
reason why int shouldn't be 64 bit on such a machine. Same on a PowerPC
in 64 bit mode.

The question is not: Why should this not work? The question is: Why
would anyone think it might work?

In embedded systems, some of the processor registers are memory mapped.
I have seen certain piece of code, where these registers are accessed
in this manner. This might not be the correct way of doing it.
In such scenarios, how these registers should be accessed ?
Is there a better way of doing it ? Or the only way is to read the
compiler's documentation to find out how it deals with integer/pointer
conversion as pointed out by "pete" in this thread earlier.
 
P

Paul Mesken

How does one accomplish this?

Pointers hold logical addresses on an x86. It's an address within a
segment. That segment might start on an odd physical address.

But I don't see any advantage in having a segment start on an
unaligned physical address :)
 
G

Gordon Burditt

An x86 processor in 32 bit mode can be
Pointers hold logical addresses on an x86. It's an address within a
segment. That segment might start on an odd physical address.

Really? How? I thought segment starting addresses were limited
to multiples of 16 (real AND protected modes), and page addresses
were limited to multiples of 4K or 4M.
But I don't see any advantage in having a segment start on an
unaligned physical address :)

It sounds like it would break most any program. And for this reason,
I believe Intel didn't even bother implementing the bits needed to
put the starting address on an odd boundary.

Gordon L. Burditt
 
P

Paul Mesken

Really? How? I thought segment starting addresses were limited
to multiples of 16 (real AND protected modes), and page addresses
were limited to multiples of 4K or 4M.

"Paging" which translates a linear address to a physical address by
means of page translation can be switched off. In such a case the
linear address (as provided by the segment descriptor) _is_ the
physical address.
It sounds like it would break most any program. And for this reason,
I believe Intel didn't even bother implementing the bits needed to
put the starting address on an odd boundary.

Come on! Don't tell me you're surprised by such things coming from
Intel ;-)
 
B

Ben Pfaff

Paul Mesken said:
But I don't see any advantage in having a segment start on an
unaligned physical address :)

It would be a lovely feature for the DS9000's cheap x86 cousin.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top