Hex to int

K

Keith Thompson

There are two ways to think about pointers. It's true that (s-1) isn't
a "valid" pointer to char, because we don't (necessarily) own the
memory before s.

It's not a valid pointer because it's outside the object, whether we
"own" the memory or not. The behavior of performing the subtraction
is not defined by the standard. (Behaving as you expect is one
possible consequence of undefined behavior -- arguably the worst,
because it makes it difficult to detect bugs.)
However, if you think about a pointer as just an address in memory,
then s-1 makes sense - it's just the location in memory before s.

But C (which is what we discuss here) doesn't define pointers as just
addresses in memory, and not all machines have the same addressing
structure. Most current machines have a simple linear address space,
and allocate objects within that space, but the C standard is
specifically designed to allow for conforming implementations on
hardware with other schemes.

Segmented architectures are not uncommon. In the extreme, an
implementation could even use a distinct segment for each individual
declared object, and cause a hardware trap if you try to compute an
address outside the object where you started.

See section 4 of the comp.lang.c FAQ said:
I think you are mistaken - I've definitely read that char *p=NULL; and
char *p=0; are completely equivalent.

Yes, they are, but no, I'm not mistaken. Both NULL and 0 are null
pointer constants. (Quibble: NULL is a macro that expands to an
implementation-defined null pointer constant.) When a null pointer
constant is used in a pointer context, it's implicitly converted to a
null pointer, which *may or may not* be represented as all-bits-zero.

For example, if a null pointer is represented as 0xFFFFFFFF, then the
declaration
char *p = 0;
will set p's representation to 0xFFFFFFFF.

See section 5 of the comp.lang.c FAQ.
 
R

rajash

Keith said:
It's not a valid pointer because it's outside the object, whether we
"own" the memory or not. The behavior of performing the subtraction
is not defined by the standard. (Behaving as you expect is one
possible consequence of undefined behavior -- arguably the worst,
because it makes it difficult to detect bugs.)


But C (which is what we discuss here) doesn't define pointers as just
addresses in memory, and not all machines have the same addressing
structure. Most current machines have a simple linear address space,
and allocate objects within that space, but the C standard is
specifically designed to allow for conforming implementations on
hardware with other schemes.

Segmented architectures are not uncommon. In the extreme, an
implementation could even use a distinct segment for each individual
declared object, and cause a hardware trap if you try to compute an
address outside the object where you started.

See section 4 of the comp.lang.c FAQ, <http://c-faq.com/>.

OK, but I'm sure I remember reading that you're allowed to have
pointers to one-beyond and one-before your allocated memory, as long
as you don't dereference them. Hum.
Yes, they are, but no, I'm not mistaken. Both NULL and 0 are null
pointer constants. (Quibble: NULL is a macro that expands to an
implementation-defined null pointer constant.) When a null pointer
constant is used in a pointer context, it's implicitly converted to a
null pointer, which *may or may not* be represented as all-bits-zero.

For example, if a null pointer is represented as 0xFFFFFFFF, then the
declaration
char *p = 0;
will set p's representation to 0xFFFFFFFF.

See section 5 of the comp.lang.c FAQ.

Interesting. So how do you create a pointer that actually points to
address 0?
 
H

Harald van Dijk

There are two ways to think about pointers. It's true that (s-1) isn't a
"valid" pointer to char, because we don't (necessarily) own the memory
before s.

However, if you think about a pointer as just an address in memory, then
s-1 makes sense - it's just the location in memory before s.

You're assuming there is a location in memory before s. This is not
always the case. But even in those cases where there is, compiler
optimisations may interfere with your expectations. The behaviour is
undefined, so don't do it.
I think you are mistaken - I've definitely read that char *p=NULL; and
char *p=0; are completely equivalent.

You read correctly, but 0 is a null pointer constant, which is not
necessarily address 0.
 
J

jameskuyper

(e-mail address removed) wrote:
....
OK, but I'm sure I remember reading that you're allowed to have
pointers to one-beyond and one-before your allocated memory, as long
as you don't dereference them. Hum.

You either remember incorrectly, or what you were reading was
incorrect. Section 6.5.6p8 says:

"Moreover, if the expression P points to the last element of an array
object, the expression (P)+1 points one past the last element of the
array object, and if the expression Q points one past the last element
of an array object,
the expression (Q)-1 points to the last element of the array object.
If both the pointer operand and the result point to elements of the
same array object, or one past the last element of the array object,
the evaluation shall not produce an overflow; otherwise, the behavior
is undefined. If the result points one past the last element of the
array object, it shall not be used as the operand of a unary *
operator that is evaluated."

There is no comparable wording for the beginning of an array, so the
"otherwise" case applies to your code.

....
Interesting. So how do you create a pointer that actually points to
address 0?

I can't think of any valid reason for doing so. If you did need to do
it, the reason would be inherently non-portable. I would strongly
suspect that on any platform where you had a legitimate need to create
a pointer pointing at address 0, you could use either

void *p = 0;

or

memset(&p, 0, sizeof p)
 
H

Harald van Dijk

OK, but I'm sure I remember reading that you're allowed to have pointers
to one-beyond and one-before your allocated memory, as long as you don't
dereference them. Hum.

Only one beyond, not one before.
I think you are mistaken - I've definitely read that char *p=NULL;
and char *p=0; are completely equivalent.

Yes, they are, but no, I'm not mistaken. [snip explanation]

See section 5 of the comp.lang.c FAQ.

Interesting. So how do you create a pointer that actually points to
address 0?

This is one of the questions in section 5 of the comp.lang.c FAQ.
Specifically, take a look at question 19.
 
C

CBFalconer

Lew said:
.... snip ...

Ben, not meaning to jiggle your elbow, but...

How is
htoi("-32" + 1)
different from
htoi("32");

Here's one way:

[1] c:\c\junk>cat junk.c
#include <stdio.h>

void htoi(const char *p) {
fprintf(stdout, "%p\n", (void*)p);
} /* htoi */

/* ------------------- */

int main(void) {

htoi("-32" + 1);
htoi("32");
return 0;
} /* main, fcopylns */

[1] c:\c\junk>cc junk.c

[1] c:\c\junk>.\a
1651
1654

:) Alternatively:

[1] c:\c\junk>cat junk.c
#include <stdio.h>

void htoi(const char *p) {
fprintf(stdout, "%p\n", (void*)p);
} /* htoi */

/* ------------------- */

int main(void) {

const char *m32 = "-32";
const char *p32 = "32";

htoi(m32 + 1);
htoi(p32);
return 0;
} /* main, fcopylns */

[1] c:\c\junk>cc junk.c

[1] c:\c\junk>.\a
1651
1654
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top