pointer offsetting

C

c.a.l

a) If i do
pointer = pointer_to_safe_thing - 1000;
pointer[1000] == pointer_to_safe_thing[0];

then
I am *not* accessing invalid memory. Nor i am incorrect in
mathematical sense.
Nevertheless outcome of pointer_to_safe_memory - 1000 operation
yielding pointer may be undefined. For i do not know whether pointers
wraparound like integers?

b) And if i do (lets say array is integer)
intprt_t i;
i = pointer_to_safe_thing - 1000;
(pointer = (int*) (i+1000) ) == pointer_to_safe_thing[0];

then
It should be correct. For integers wraparound (should?).

Am i correct? I feel that it depends on what type of number system
computer uses.
Thank you in advance.
 
W

Walter Roberson

a) If i do
pointer = pointer_to_safe_thing - 1000;
pointer[1000] == pointer_to_safe_thing[0];
then
I am *not* accessing invalid memory. Nor i am incorrect in
mathematical sense.
Nevertheless outcome of pointer_to_safe_memory - 1000 operation
yielding pointer may be undefined. For i do not know whether pointers
wraparound like integers?

Implementation dependant. You can only *safely* have a pointer
that is NULL, or points into an object, or points "one past" the end
of the object.

b) And if i do (lets say array is integer)
intprt_t i;

Did you perhaps mean intptr_t ?
i = pointer_to_safe_thing - 1000;
(pointer = (int*) (i+1000) ) == pointer_to_safe_thing[0];
then
It should be correct. For integers wraparound (should?).

Only unsigned integers are certain to wraparound; signed
integers are permitted to "saturate" or produce other oddities
in artithmetic.
 
K

Keith Thompson

a) If i do
pointer = pointer_to_safe_thing - 1000;
pointer[1000] == pointer_to_safe_thing[0];

then
I am *not* accessing invalid memory. Nor i am incorrect in
mathematical sense.
Nevertheless outcome of pointer_to_safe_memory - 1000 operation
yielding pointer may be undefined. For i do not know whether pointers
wraparound like integers?

Right, evaluating the expression pointer_to_safe_thing - 1000 invokes
undefined behavior (note: *not* just an undefined value). This
doesn't necesssarily have anything to do with wraparound; the behavior
is undefined because the standard says so.
b) And if i do (lets say array is integer)
intprt_t i;
i = pointer_to_safe_thing - 1000;
(pointer = (int*) (i+1000) ) == pointer_to_safe_thing[0];

then
It should be correct. For integers wraparound (should?).

I'm not quite sure what you're doing here. Presumably intprt_t is a
typo for intptr_t. There happens to be a type by that name, declared
in <stdint.h>; it's a signed integer type capable of holding pointer
values. The result of ``pointer_to_safe_thing - 1000'' is of a
pointer type, not an integer type. The assignment is illegal; there's
no implicit conversion from pointers to integers.

If you make it legal by adding a cast, then you get some arbitrary
integer value; all you know about it is that you ca convert the same
value back to a pointer type and get back the original pointer value.
(Actually for intptr_t that guarantee applies only to void*.)

If intptr_t is meant to be a pointer type (int*?), then you have
exactly the same problem as in your first example.

If you can reconstruct your second example with code that will
actually compile, we can help you figure out whether the behavior is
defined. My guess is that you won't be able to do so without
producing something that's equivalent to your first example.
Am i correct? I feel that it depends on what type of number system
computer uses.

It could depend on any number of things. The standard says that the
behavior of certain operations is undefined; it doesn't necessarily
say why.

Here's another example that may or may not be relevant and/or
instructive:

int obj;
int *valid_pointer = &obj;
(valid_pointer + 1000) - 1000; /* undefined behavior */
valid_pointer + 1000 - 1000; /* equivalent to the above */
valid_pointer + (1000 - 1000); /* ok */
 
C

c.a.l

Thanks You both much for explanation.

b) And if i do (lets say array is integer)
intprt_t i;
i = pointer_to_safe_thing - 1000;
(pointer = (int*) (i+1000) ) == pointer_to_safe_thing[0];
then
It should be correct. For integers wraparound (should?).

I'm not quite sure what you're doing here. Presumably intprt_t is a
typo for intptr_t. There happens to be a type by that name, declared
in <stdint.h>; it's a signed integer type capable of holding pointer
values.

Yes, i ment integer type capable of holding pointer value. Sorry i
misspelled.
The result of ``pointer_to_safe_thing - 1000'' is of a
pointer type, not an integer type. The assignment is illegal; there's
no implicit conversion from pointers to integers.

Thanks i blindly presumed that for this type it is done;) Now i
checked that
it is not true.
If you make it legal by adding a cast, then you get some arbitrary
integer value; all you know about it is that you ca convert the same
value back to a pointer type and get back the original pointer value.
(Actually for intptr_t that guarantee applies only to void*.)

Now i think that safe way might be something like:

object_t* p = & obj;
object_t* newptr = NULL; /* just for dereferencing */
uintptr_t vp = 0;

vp = (intptr) (void*) p;
vp = vp + INTPTR_MAX * sizeof(*p); /* to overflow + keep alignment */
newptr = (object_t*) (void*) (vp - INTPTR_MAX * sizeof(*p));
assert (newptr == p);

a) If i'd use intptr_t instead, wraparound is not guaranteed (it is
signed value!)?
b) Was this void* cast necessary for transfering values from, to
uintptr_t?
c) Was the way i have used it with stepping by sizeof(*p) correct?
Emulation of stepping a pointer to a type ala
array[5] = array + 5 = (char*) array + 5 * (sizeof(array[0])/
sizeof(char))?
 
K

Keith Thompson

Thanks You both much for explanation. [...]
Now i think that safe way might be something like:

The safe way to do what?
object_t* p = & obj;
object_t* newptr = NULL; /* just for dereferencing */
uintptr_t vp = 0;

You assign values to newptr and vp; why initialize them?
vp = (intptr) (void*) p;

I think you meant:

vp = (uintptr_t)(void*)p;

This obtains a valid uintptr_t value by conversion from a valid
pointer value. So far, so good.
vp = vp + INTPTR_MAX * sizeof(*p); /* to overflow + keep alignment */

You can convert a void* value to uintptr_t. Converting the result
back to void* is guaranteed to give you back the original void* value.
That's the *only* thing that's guaranteed. If you modify the
uintptr_t value in any way, converting it back to void* is meaningless
(even if it happens to work on your platform). You can do anything
you like with it *as an integer*, but you've lost the association with
any meaningful pointer value.

I can't figure out what the above statement is supposed to do anyway.
For one thing, you're mixing intptr_t and uintptr_t values.
newptr = (object_t*) (void*) (vp - INTPTR_MAX * sizeof(*p));

Garbage in, garbage out.
assert (newptr == p);

a) If i'd use intptr_t instead, wraparound is not guaranteed (it is
signed value!)?

Since uintptr_t is an unsigned type, arithmetic on it has wraparound
semantics. Since intptr_t is signed, overflow invokes undefined
behavior. Neither of these is relevant in any portable way to their
relationship to pointers.
b) Was this void* cast necessary for transfering values from, to
uintptr_t?

I think so.
c) Was the way i have used it with stepping by sizeof(*p) correct?
Emulation of stepping a pointer to a type ala
array[5] = array + 5 = (char*) array + 5 * (sizeof(array[0])/
sizeof(char))?

No, though it might happen to work on your platform.
 
B

Barry Schwarz

a) If i do
pointer = pointer_to_safe_thing - 1000;
pointer[1000] == pointer_to_safe_thing[0];
then
I am *not* accessing invalid memory. Nor i am incorrect in
mathematical sense.
Nevertheless outcome of pointer_to_safe_memory - 1000 operation
yielding pointer may be undefined. For i do not know whether pointers
wraparound like integers?

Implementation dependant. You can only *safely* have a pointer
that is NULL, or points into an object, or points "one past" the end
of the object.

Nope. It is undefined behavior (n1124, 6.5.6-8)



Remove del for email
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

a) If i do
pointer = pointer_to_safe_thing - 1000; pointer[1000] ==
pointer_to_safe_thing[0];
then
I am *not* accessing invalid memory. Nor i am incorrect in mathematical
sense.
Nevertheless outcome of pointer_to_safe_memory - 1000 operation
yielding pointer may be undefined. For i do not know whether pointers
wraparound like integers?

Implementation dependant. You can only *safely* have a pointer that is
NULL, or points into an object, or points "one past" the end of the
object.

Nope. It is undefined behavior

Undefined behaviour is inherently implementation dependent.
(n1124, 6.5.6-8)

If you're going to refer to a draft, could you please refer to n1256?
It's available in the same format as n1124 (PDF), but it's more recent.
 
J

Joachim Schmitz

Harald van D?k said:
a) If i do
pointer = pointer_to_safe_thing - 1000; pointer[1000] ==
pointer_to_safe_thing[0];

then
I am *not* accessing invalid memory. Nor i am incorrect in mathematical
sense.
Nevertheless outcome of pointer_to_safe_memory - 1000 operation
yielding pointer may be undefined. For i do not know whether pointers
wraparound like integers?

Implementation dependant. You can only *safely* have a pointer that is
NULL, or points into an object, or points "one past" the end of the
object.

Nope. It is undefined behavior

Undefined behaviour is inherently implementation dependent.
(n1124, 6.5.6-8)

If you're going to refer to a draft, could you please refer to n1256?
n1124 is not a draft, it is C99 plus TC 1 and TC2, while n1256 is C99 + Tc1,
TC2 and TC3.
Or if n1124 is a draft, n1256 is one too
The pre C99 draft has a 3 digit namber which escapes me at this moment...
It's available in the same format as n1124 (PDF), but it's more recent.
True

Bye, Jojo
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

n1124 is not a draft, it is C99 plus TC 1 and TC2,

As I recall, some DRs have been resolved between TC2 and n1124. n1124 is
a draft, and different from C99+TC1+TC2.
while n1256 is C99 +
Tc1, TC2 and TC3.

I do not know if n1256 differs from C99+TC1+TC2+TC3. C99 TC3 does not
appear to be available yet.
Or if n1124 is a draft, n1256 is one too The pre C99 draft has a 3 digit
namber which escapes me at this moment...

n869, which has the advantage of being available in plain text format.
 
K

Keith Thompson

It calls itself a draft. Each page has the following header

ISO/IEC 9899:TC2 Committee Draft ? May 6, 2005 WG14/N1124

and each page of n1256.pdf has:

ISO/IEC 9899:TC3 Committee Draft ? Septermber 7, 2007 WG14/N1256

(Well, close enough. Alternating pages change the ordering, and page
1 differs.)
As I recall, some DRs have been resolved between TC2 and n1124. n1124 is
a draft, and different from C99+TC1+TC2.

Really? That's news to me (and the "ISO/IEC 9899:TC2" in the page
headers seems to imply otherwise). Can you or someone else confirm
this, preferably with details?
I do not know if n1256 differs from C99+TC1+TC2+TC3. C99 TC3 does not
appear to be available yet.

It is; you can download
n869, which has the advantage of being available in plain text format.

PDF can be converted to plain text (with some loss of information).
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

It calls itself a draft. Each page has the following header

ISO/IEC 9899:TC2 Committee Draft ? May 6, 2005 WG14/N1124

and each page of n1256.pdf has:

ISO/IEC 9899:TC3 Committee Draft ? Septermber 7, 2007 WG14/N1256

(Well, close enough. Alternating pages change the ordering, and page 1
differs.)


Really? That's news to me (and the "ISO/IEC 9899:TC2" in the page
headers seems to imply otherwise). Can you or someone else confirm
this, preferably with details?

C99+TC1+TC2 6.7p7: (typed over from C99+TC1, verified that no changes
were made from 9899-1999_cor_2-2004.pdf)
"If an identifier for an object is declared with no linkage, the type for
the object shall be complete by the end of its declarator, or by the end
of its init-declarator if it has an initializer; in the fase of function
arguments (including in prototypes), it is the adjusted type (see
6.7.5.3) that is required to be complete."

n1124 6.7p7:
"If an identifier for an object is declared with no linkage, the type for
the object shall be complete by the end of its declarator, or by the end
of its init-declarator if it has an initializer; in the case of function
parameters (including in prototypes), it is the adjusted type (see
6.7.5.3) that is required to be complete."

This change (arguments -> parameters) is DR #295, marked on
It is; you can download


PDF can be converted to plain text (with some loss of information).

True; I've used pdftotext on both n1124 and n1256 myself. Unfortunately I
haven't managed to convert it to plain text without getting the ï¬ symbol
instead of fi, and other similar problems, which causes problems when
copying and pasting. That's where n869 is nice.
 
P

Peter Pichler

Keith said:
b) And if i do (lets say array is integer)
intprt_t i;
i = pointer_to_safe_thing - 1000;
(pointer = (int*) (i+1000) ) == pointer_to_safe_thing[0];

then
It should be correct. For integers wraparound (should?).

I'm not quite sure what you're doing here. Presumably intprt_t is a
typo for intptr_t. There happens to be a type by that name, declared
in <stdint.h>; it's a signed integer type capable of holding pointer
values. The result of ``pointer_to_safe_thing - 1000'' is of a
pointer type, not an integer type. The assignment is illegal; there's
no implicit conversion from pointers to integers.

If you make it legal by adding a cast, then you get some arbitrary
integer value; all you know about it is that you ca convert the same
value back to a pointer type and get back the original pointer value.
(Actually for intptr_t that guarantee applies only to void*.)

He might get away with casting the pointer first, before subtracting
1000. The rest is just integer arithmetic. It may still fall down if i
overflows.
 
K

Keith Thompson

Peter Pichler said:
Keith said:
b) And if i do (lets say array is integer)
intprt_t i;
i = pointer_to_safe_thing - 1000;
(pointer = (int*) (i+1000) ) == pointer_to_safe_thing[0];

then
It should be correct. For integers wraparound (should?).
I'm not quite sure what you're doing here. Presumably intprt_t is a
typo for intptr_t. There happens to be a type by that name, declared
in <stdint.h>; it's a signed integer type capable of holding pointer
values. The result of ``pointer_to_safe_thing - 1000'' is of a
pointer type, not an integer type. The assignment is illegal; there's
no implicit conversion from pointers to integers.
If you make it legal by adding a cast, then you get some arbitrary
integer value; all you know about it is that you ca convert the same
value back to a pointer type and get back the original pointer value.
(Actually for intptr_t that guarantee applies only to void*.)

He might get away with casting the pointer first, before subtracting
1000. The rest is just integer arithmetic. It may still fall down if i
overflows.

Sure, once he has an integer value, he can perform any arithmetic he
likes on it, as long as it doesn't overflow or divide by zero. And if
it's an unsigned type such as uintptr_t, he doesn't have to worry
about overflow.

But what's the point? If you convert a pointer value to uintptr_t,
the only meaningful thing you can do with it is convert it back to a
pointer. If you modify the uintptr_t value and then convert the
modified result to uintptr_t, the result is completely meaningless as
far as the standard is concerned.

You might be able to do something meaningful with the integer value in
some implementations. For example, examining the low-order bits might
tell you something about alignment. But that's not guaranteed.
 
C

CBFalconer

Keith said:
.... snip ...


PDF can be converted to plain text (with some loss of information).

N869 is available in a properly formatted text version, unlike the
others. So called 'text conversion' just leaves a mess. After
page information is stripped from N869, and the indentation is
reduced, the result is available (compressed) as n869_txt.bz2 at:

<http://cbfalconer.home.att.net/download/>

and is quite suitable for quoting, grepping, etc.
 
L

lawrence.jones

Keith Thompson said:
Really? That's news to me (and the "ISO/IEC 9899:TC2" in the page
headers seems to imply otherwise). Can you or someone else confirm
this, preferably with details?

N1124 was intended to be substantively identical to C99+TC1+TC2 just as
N1256 is intended to be substantively identical to C99+TC1+TC2+TC3.
However, the editor (yours truly) reserves the right to make editorial
changes in the process of applying the TCs to make the text read better
and has also been known to slip in minor editorial changes in the
process (e.g., somewhere along the way, I switched from "one's
complement" to "ones' complement" based on Knuth's argument for the
latter and there have also been a number of improvements to the index).
Non-trivial changes usually show up in a "cleanup" DR to be formally
adopted by the committee, but we don't always bother for trivial and
inconsequential changes (such as the index changes).

The only significant difference I know of in N1124 is that TC2 made a
change to the description of the "g" conversion specifier in the
description of fprintf in 7.19.6.1 but did not make the parallel change
to the description of fwprintf in 7.24.2.1. Since the same source code
is used for both, N1124 does have the change to 7.24.2.1 even though it
wasn't formally adopted until TC3.

-Larry Jones

The hardest part for us avant-garde post-modern artists is
deciding whether or not to embrace commercialism. -- Calvin
 
C

CBFalconer

.... snip ...

The only significant difference I know of in N1124 is that TC2
made a change to the description of the "g" conversion specifier
in the description of fprintf in 7.19.6.1 but did not make the
parallel change to the description of fwprintf in 7.24.2.1.
Since the same source code is used for both, N1124 does have the
change to 7.24.2.1 even though it wasn't formally adopted until
TC3.

Glad to see you here. Please consider publishing a text version of
N1256, as you [1] did for N869. This is much more useful than a
PDF version for many purposes.

[1] collective you :)
 
B

Barry Schwarz

a) If i do
pointer = pointer_to_safe_thing - 1000; pointer[1000] ==
pointer_to_safe_thing[0];

then
I am *not* accessing invalid memory. Nor i am incorrect in mathematical
sense.
Nevertheless outcome of pointer_to_safe_memory - 1000 operation
yielding pointer may be undefined. For i do not know whether pointers
wraparound like integers?

Implementation dependant. You can only *safely* have a pointer that is
NULL, or points into an object, or points "one past" the end of the
object.

Nope. It is undefined behavior

Undefined behaviour is inherently implementation dependent.
Implementation dependent implies that the behavior will be consistent
on a particular implementation (the same today as it was yesterday).
Undefined behavior is not so constrained.


Remove del for email
 
J

James Kuyper Jr.

Barry said:
On Sun, 14 Oct 2007 12:44:02 +0000 (UTC), $)CHarald van D)&k

Implementation dependent implies that the behavior will be consistent
on a particular implementation (the same today as it was yesterday).

Citation, please?

"Implementation-dependent behavior" isn't a term defined in the C
standard. It's normal English meaning is only that the behavior depends
upon which implementation you use, which is certainly true for undefined
behavior. I don't see any implication that the behavior has to be
consistent.
 

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,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top