468,491 Members | 2,079 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,491 developers. It's quick & easy.

Hex to int

Thanks to everyone for interesting discussions. To make the group
happy, my next listing has int main and headers declared!!

Here is my solution to Exercise 2.3.

// write htoi, hex to int

#include<stdio.h>

int main(int c, char **v)
{
int x=-1, htoi();
if(c>1)
x=htoi(v[1]);
if(x>=0)
printf("%d\n", x);
else
printf("Unspecified error.\n");
}

int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {
if('0' <= *s && *s <= '9')
x+=y*(*s - '0');
else if('a' <= *s && *s <= 'f')
x+=y*(*s - 'a' + 10);
else if('A' <= *s && *s <= 'F')
x+=y*(10 + *s - 'A');
else
return -1; /* invalid input! */
y<<=4;
}
return x;
}
Dec 2 '07 #1
25 5320
ra****@thisisnotmyrealemail.com writes:
Thanks to everyone for interesting discussions. To make the group
happy, my next listing has int main and headers declared!!

Here is my solution to Exercise 2.3.

// write htoi, hex to int

#include<stdio.h>

int main(int c, char **v)
The traditional names for the parameters to main() are argc and argv.
Using different names is legal, but a very bad idea; it just makes
your code more difficult to read.
{
int x=-1, htoi();
Putting a function declaration inside a function definition is legal,
but not a good idea. A function declaration with empty parentheses
says that the function takes a fixed but unspecied number and type(s)
of arguments.

Either declare htoi() with a full prototype at file scope (outside main()):

int htoi(char *s);

or move the full definition of htoi() above the definition of main(),
so you don't need a separate declaration.
if(c>1)
x=htoi(v[1]);
if(x>=0)
printf("%d\n", x);
else
printf("Unspecified error.\n");
Error messages are normally printed to stderr, not stdout.

You could detect the specific error of invoking main() with no
arguments. Consider something like this:

if (argc <= 1) {
fprintf(stderr, "Usage: %s arg\n", argv[0]);
exit(EXIT_FAILURE);
}
}

int htoi(char *s)
Consider declaring this static, since it's not used from any other
translation units.
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {
if('0' <= *s && *s <= '9')
You can use the isdigit() function for this.
x+=y*(*s - '0');
else if('a' <= *s && *s <= 'f')
x+=y*(*s - 'a' + 10);
else if('A' <= *s && *s <= 'F')
x+=y*(10 + *s - 'A');
You're assuming that the numeric codes for the letters 'a'..'f' and
'A'..'F' are contiguous. This is not guaranteed, and there are
character sets where the alphabet is not contiguous (though in the one
example of this that I know of, 'a'..'f' and 'A'..'F' happen to be
contiguous). Consider using the isxdigit() function.
else
return -1; /* invalid input! */
y<<=4;
}
return x;
}
These are mostly superficial points. I'd take a closer look at the
algorithm, but your use of meaningless single-character identifiers
makes your code difficult to read.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Dec 2 '07 #2
ra****@thisisnotmyrealemail.com wrote, On 02/12/07 22:01:
Thanks to everyone for interesting discussions. To make the group
happy, my next listing has int main and headers declared!!
If your only reason for doing it is to keep the group happy then you
don't understand the issues and should reread what people have told you.
Either that or choose something other than programming.

Also you have *not* included all the required headers.
Here is my solution to Exercise 2.3.

// write htoi, hex to int

#include<stdio.h>
The space shortage ended some years back, so it will be easier to read
if you use some
#include <stdio.h>
int main(int c, char **v)
Conventionally the parameters are called argc and argv. Although other
names are legal it makes it easier for everyone if you use the
conventional names.
{
int x=-1, htoi();
Very bad style on two counts.
1) You have not used the prototype style of declaration so the compiler
cannot check the number and type of parameters passed to htoi.
2) It is generally considered better to not declare the functions
locally but globally, since they are visible globally. So it would be
better to put "int htoi(char *s);" at file scope or define htos prior to
main.
if(c>1)
x=htoi(v[1]);
if(x>=0)
printf("%d\n", x);
else
printf("Unspecified error.\n");
How about returning the value from main that the return type promisses
will be returned?
}

int htoi(char *s)
{
char *t=s;
int x=0, y=1;
Why not try using more than one character for variable names? It makes
it *far* easier to read if you use meaningful names.
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
You need string.h for strlen, without it your program invokes undefined
behaviour and could fail on some implementations, for example if size_t
(the return type of strlen) is 64 bits but int is only 32 bits.
while(t<=--s) {
if('0' <= *s && *s <= '9')
x+=y*(*s - '0');
else if('a' <= *s && *s <= 'f')
x+=y*(*s - 'a' + 10);
The letters are not guaranteed to be consecutive and one some systems
they are not.
else if('A' <= *s && *s <= 'F')
x+=y*(10 + *s - 'A');
else
return -1; /* invalid input! */
y<<=4;
None of the above handles overflow properly. Overflow of signed types
invokes undefined behaviour and might not (on some implementations will
not) do what you expect.
}
return x;
}
--
Flash Gordon
Dec 3 '07 #3
ra****@thisisnotmyrealemail.com writes:
Here is my solution to Exercise 2.3.
<snip>

I'll comment only on the thing not yet pointed out...
int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {
This loop condition is likely to invoke undefined behaviour. Can you
see why?

--
Ben.
Dec 3 '07 #4
On Dec 3, 3:11 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
raj...@thisisnotmyrealemail.com writes:
Here is my solution to Exercise 2.3.

<snip>

I'll comment only on the thing not yet pointed out...
int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {

This loop condition is likely to invoke undefined behaviour. Can you
see why?
If strlen(s) equals 0.
Dec 3 '07 #5
vi******@gmail.com writes:
On Dec 3, 3:11 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>raj...@thisisnotmyrealemail.com writes:
Here is my solution to Exercise 2.3.

<snip>

I'll comment only on the thing not yet pointed out...
int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {

This loop condition is likely to invoke undefined behaviour. Can you
see why?

If strlen(s) equals 0.
No. It can invoke UB when strlen(s) != 0 and it may not invoke UB in
some cases when strlen(s) == 0. Anyway, the question was partly
rhetorical. I think people learn better when they think, so I rather
hoped that my question would remain unanswered (at least for some while).

--
Ben.
Dec 3 '07 #6
RoS
In data Mon, 03 Dec 2007 13:11:05 +0000, Ben Bacarisse scrisse:
>rajash@thisisnotmyrealemail writes:
>Here is my solution to Exercise 2.3.
<snip>

I'll comment only on the thing not yet pointed out...
>int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {

This loop condition is likely to invoke undefined behaviour. Can you
see why?
is it because if s point to "" =strlen(s)==0; (s+=0)==s and --s
point to memory not allowed to change (or read)?
Dec 3 '07 #7
RoS <Ro*@not.existwrites:
In data Mon, 03 Dec 2007 13:11:05 +0000, Ben Bacarisse scrisse:
>>rajash@thisisnotmyrealemail writes:
>>Here is my solution to Exercise 2.3.
<snip>

I'll comment only on the thing not yet pointed out...
>>int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {

This loop condition is likely to invoke undefined behaviour. Can you
see why?

is it because if s point to "" =strlen(s)==0; (s+=0)==s and --s
point to memory not allowed to change (or read)?
s pointing to "" and/or strlen(s) being zero has nothing to do with
it. Just consider a simple call like htoi("20") and work out what has
to happen for the while loop to stop.

Whenever I see a while loop, I negate the test in my head as ask "is
this condition safe?". When there is code after the loop you can
check that that code makes sense in an environment where the loop
condition is false (not significant in this case).

It gets a little messy when there are assignment operators (and
equivalents) in the test but it is still worth doing. In languages
like C, you have to scan the body for breaks, gotos and returns but
that is simple enough.

--
Ben.
Dec 3 '07 #8
Ben Bacarisse wrote:
ra****@thisisnotmyrealemail.com writes:
Here is my solution to Exercise 2.3.
<snip>

I'll comment only on the thing not yet pointed out...
int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {

This loop condition is likely to invoke undefined behaviour. Can you
see why?
No.
Dec 3 '07 #9
ra****@thisisnotmyrealemail.com wrote:
Ben Bacarisse wrote:
>ra****@thisisnotmyrealemail.com writes:
>>Here is my solution to Exercise 2.3.
<snip>

I'll comment only on the thing not yet pointed out...
>>int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {
This loop condition is likely to invoke undefined behaviour. Can you
see why?

No.
For a string not prefixed by "0x" or "0X", what happens to s if t==s at
the time the loop condition is evaluated?
Dec 4 '07 #10
James Kuyper <ja*********@verizon.netwrites:
ra****@thisisnotmyrealemail.com wrote:
>Ben Bacarisse wrote:
>>ra****@thisisnotmyrealemail.com writes:

Here is my solution to Exercise 2.3.
<snip>

I'll comment only on the thing not yet pointed out...

int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {
This loop condition is likely to invoke undefined behaviour. Can you
see why?

No.

For a string not prefixed by "0x" or "0X", what happens to s if t==s
at the time the loop condition is evaluated?
Thanks. I was going to get back to this, it just took me a bit of
time...

If the OP needs any more hints: UB occurs whenever the function is
called with a pointer to the start of an object which does not begin
"0x" or "0X". htoi("-32" + 1) and htoi("0x32") are OK, but htoi("32")
is not.

--
Ben.
Dec 4 '07 #11
On Dec 4, 9:22 am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
James Kuyper <jameskuy...@verizon.netwrites:
raj...@thisisnotmyrealemail.com wrote:
Ben Bacarisse wrote:
raj...@thisisnotmyrealemail.com writes:
>>Here is my solution to Exercise 2.3.
<snip>
>I'll comment only on the thing not yet pointed out...
>>int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {
This loop condition is likely to invoke undefined behaviour. Can you
see why?
No.
For a string not prefixed by "0x" or "0X", what happens to s if t==s
at the time the loop condition is evaluated?

Thanks. I was going to get back to this, it just took me a bit of
time...

If the OP needs any more hints: UB occurs whenever the function is
called with a pointer to the start of an object which does not begin
"0x" or "0X". htoi("-32" + 1) and htoi("0x32") are OK, but htoi("32")
is not.
Ben, not meaning to jiggle your elbow, but...

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

Just trying to understand your point here

Dec 4 '07 #12
Lew Pitcher <lp******@teksavvy.comwrites:
On Dec 4, 9:22 am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>James Kuyper <jameskuy...@verizon.netwrites:
raj...@thisisnotmyrealemail.com wrote:
Ben Bacarisse wrote:
raj...@thisisnotmyrealemail.com writes:
>>>Here is my solution to Exercise 2.3.
<snip>
>>I'll comment only on the thing not yet pointed out...
>>>int htoi(char *s)
{
char *t=s;
int x=0, y=1;
if(*s=='0' && (s[1]=='x' || s[1]=='X'))
t+=2;
s+=strlen(s);
while(t<=--s) {
This loop condition is likely to invoke undefined behaviour. Can you
see why?
>No.
For a string not prefixed by "0x" or "0X", what happens to s if t==s
at the time the loop condition is evaluated?

Thanks. I was going to get back to this, it just took me a bit of
time...

If the OP needs any more hints: UB occurs whenever the function is
called with a pointer to the start of an object which does not begin
"0x" or "0X". htoi("-32" + 1) and htoi("0x32") are OK, but htoi("32")
is not.

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

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

Just trying to understand your point here
I was not trying to be cute and obscure. Here's my version of the
problem. I hope I have not made a mistake with all this!

In the call htoi("-32" + 1) s points one byte into an object so the
terminating condition of the loop 't <= --s' is met when s points at
the '-'. If the string has no "0x" prefix, the terminating condition
is met when s has been decremented to make a pointer that points
before the start of the object. This, I think, is not allowed.

--s is defined to mean the same as s -= 1 and s -= 1 is defined to
mean the same as s = s - 1 (but the lvalue s is not evaluated twice).
Thus section 6.5.6 (which describes + and -) governs what pointer
arithmetic you can do with --. Paragraph 8 says that the result is
well defined only when the resulting pointer points into, or just
past, the object. You don't have to de-reference the pointer to get
UB -- the arithmetic alone is enough (although * applied to the "just
past the end" pointer is also undefined).

--
Ben.
Dec 4 '07 #13
Lew Pitcher wrote:
On Dec 4, 9:22 am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
....
If the OP needs any more hints: UB occurs whenever the function is
called with a pointer to the start of an object which does not begin
"0x" or "0X". htoi("-32" + 1) and htoi("0x32") are OK, but htoi("32")
is not.

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

How is
htoi("-32" + 1)
different from
htoi("32");
Trace through the original code; the '-' is recognized as an invalid
character, resulting in an early exit from the loop just one step
before it would otherwise have had undefined behavior.
Dec 4 '07 #14
On Dec 4, 12:11 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Lew Pitcher <lpitc...@teksavvy.comwrites:
On Dec 4, 9:22 am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:[snip]
If the OP needs any more hints: UB occurs whenever the function is
called with a pointer to the start of an object which does not begin
"0x" or "0X". htoi("-32" + 1) and htoi("0x32") are OK, but htoi("32")
is not.
Ben, not meaning to jiggle your elbow, but...
How is
htoi("-32" + 1)
different from
htoi("32");
?
Just trying to understand your point here

I was not trying to be cute and obscure. Here's my version of the
problem. I hope I have not made a mistake with all this!

In the call htoi("-32" + 1) s points one byte into an object so the
terminating condition of the loop 't <= --s' is met when s points at
the '-'. If the string has no "0x" prefix, the terminating condition
is met when s has been decremented to make a pointer that points
before the start of the object. This, I think, is not allowed.
Thanks, Ben. I knew I was missing something.

--
Lew
Dec 4 '07 #15
ja*********@verizon.net writes:
Lew Pitcher wrote:
>On Dec 4, 9:22 am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
...
If the OP needs any more hints: UB occurs whenever the function is
called with a pointer to the start of an object which does not begin
"0x" or "0X". htoi("-32" + 1) and htoi("0x32") are OK, but htoi("32")
is not.

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

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

Trace through the original code; the '-' is recognized as an invalid
character, resulting in an early exit from the loop just one step
before it would otherwise have had undefined behavior.
Not quite. The function copies 's' to 't' and then loops 'while (t <=
--s)' so the inner test for invalid characters never sees the '-' in a
call like htoi("-32" + 1). The +1 simply avoids the UB by passing a
pointer that is not the start of an object. htoi("-32") would avoid
the UB for exactly the reasons you give.

The big point here is that running pointer loops backwards is tricky
and needs extra care because there is no special right to "go off the
end" (even by one) in that direction.

--
Ben.
Dec 4 '07 #16
James Kuyper wrote:
For a string not prefixed by "0x" or "0X", what happens to s if t==s at
the time the loop condition is evaluated?
Then --s will evaluate to the address one before the pointer
originally passed to the function. This would only cause a problem if
the original pointer was to address 0, but in that case it would be a
NULL pointer, which isn't allowed (the argument given to htoi must be
a STRING).
Dec 4 '07 #17
ra****@thisisnotmyrealemail.com writes:
James Kuyper wrote:
>For a string not prefixed by "0x" or "0X", what happens to s if t==s at
the time the loop condition is evaluated?

Then --s will evaluate to the address one before the pointer
originally passed to the function. This would only cause a problem if
the original pointer was to address 0, but in that case it would be a
NULL pointer, which isn't allowed (the argument given to htoi must be
a STRING).
No, if the passed pointer points to the beginning of an object (as
opposed to the "-32"+1 example elsethread), then attempting to point
before the beginning of the object invokes undefined behavior. For
example, given:

char *s = "hello";

just evaluating (s-1), even without attempting to dereference it,
invokes UB.

Furthermore, address 0 is not necessarily the same as a null pointer.
(The FAQ, www.c-faq.com, has an entire section on null pointers.)

It may be that some implementations will happen to behave as you say,
but that's not guaranteed by the standard.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Dec 4 '07 #18
ra****@thisisnotmyrealemail.com wrote, On 04/12/07 19:40:
James Kuyper wrote:
>For a string not prefixed by "0x" or "0X", what happens to s if t==s at
the time the loop condition is evaluated?

Then --s will evaluate to the address one before the pointer
originally passed to the function. This would only cause a problem if
the original pointer was to address 0,
Incorrect. Calculating a pointer to before the object you started in (as
in this case) ALWAYS invokes undefined behaviour. On a lot of
implementations (probably most) it does what the programmer would
expect, but bounds checking implementations that detect this and abort
the program are not only legal but useful.
but in that case it would be a
NULL pointer,
Not necessarily true. The null pointer might not be all bits 0 (i.e. an
address or 0) and a pointer with all bits 0 could well be a valid
pointer (i.e. not a null pointer). There are even sensible reasons why
one might do this.

A 0 in the source code used in a pointer context is another matter, and
the implementation has to do whatever magic is required to make it work,
even if that means "int *p = 0;" does not set p to all bits 0.
which isn't allowed (the argument given to htoi must be
a STRING).
Actually, it must be a pointer to the first character of a string, but
you were almost correct on this bit ;-)
--
Flash Gordon
Dec 4 '07 #19
Keith Thompson wrote:
ra****@thisisnotmyrealemail.com writes:
James Kuyper wrote:
For a string not prefixed by "0x" or "0X", what happens to s if t==s at
the time the loop condition is evaluated?
Then --s will evaluate to the address one before the pointer
originally passed to the function. This would only cause a problem if
the original pointer was to address 0, but in that case it would be a
NULL pointer, which isn't allowed (the argument given to htoi must be
a STRING).

No, if the passed pointer points to the beginning of an object (as
opposed to the "-32"+1 example elsethread), then attempting to point
before the beginning of the object invokes undefined behavior. For
example, given:

char *s = "hello";

just evaluating (s-1), even without attempting to dereference it,
invokes UB.
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.
Furthermore, address 0 is not necessarily the same as a null pointer.
(The FAQ, www.c-faq.com, has an entire section on null pointers.)

It may be that some implementations will happen to behave as you say,
but that's not guaranteed by the standard.
I think you are mistaken - I've definitely read that char *p=NULL; and
char *p=0; are completely equivalent.
Dec 4 '07 #20
On Tue, 04 Dec 2007 13:39:11 -0800, rajash wrote:
Keith Thompson wrote:
>ra****@thisisnotmyrealemail.com writes:
James Kuyper wrote:
For a string not prefixed by "0x" or "0X", what happens to s if t==s
at the time the loop condition is evaluated?

Then --s will evaluate to the address one before the pointer
originally passed to the function. This would only cause a problem if
the original pointer was to address 0, but in that case it would be a
NULL pointer, which isn't allowed (the argument given to htoi must be
a STRING).

No, if the passed pointer points to the beginning of an object (as
opposed to the "-32"+1 example elsethread), then attempting to point
before the beginning of the object invokes undefined behavior. For
example, given:

char *s = "hello";

just evaluating (s-1), even without attempting to dereference it,
invokes UB.

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.
>Furthermore, address 0 is not necessarily the same as a null pointer.
(The FAQ, www.c-faq.com, has an entire section on null pointers.)

It may be that some implementations will happen to behave as you say,
but that's not guaranteed by the standard.

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.
Dec 4 '07 #21
ra****@thisisnotmyrealemail.com writes:
Keith Thompson wrote:
>ra****@thisisnotmyrealemail.com writes:
James Kuyper wrote:
For a string not prefixed by "0x" or "0X", what happens to s if t==s at
the time the loop condition is evaluated?

Then --s will evaluate to the address one before the pointer
originally passed to the function. This would only cause a problem if
the original pointer was to address 0, but in that case it would be a
NULL pointer, which isn't allowed (the argument given to htoi must be
a STRING).

No, if the passed pointer points to the beginning of an object (as
opposed to the "-32"+1 example elsethread), then attempting to point
before the beginning of the object invokes undefined behavior. For
example, given:

char *s = "hello";

just evaluating (s-1), even without attempting to dereference it,
invokes UB.

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, <http://c-faq.com/>.
>Furthermore, address 0 is not necessarily the same as a null pointer.
(The FAQ, www.c-faq.com, has an entire section on null pointers.)

It may be that some implementations will happen to behave as you say,
but that's not guaranteed by the standard.

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.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Dec 4 '07 #22
Keith Thompson wrote:
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, <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.
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.
Interesting. So how do you create a pointer that actually points to
address 0?
Dec 4 '07 #23
On Tue, 04 Dec 2007 14:08:36 -0800, rajash 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.
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.
Dec 4 '07 #24
raj...@thisisnotmyrealemail.com 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)
Dec 4 '07 #25
Lew Pitcher wrote:
>
.... 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

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Dec 5 '07 #26

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by William C. White | last post: by
2 posts views Thread by Albert Ahtenberg | last post: by
3 posts views Thread by James | last post: by
reply views Thread by Ollivier Robert | last post: by
1 post views Thread by Richard Galli | last post: by
4 posts views Thread by Albert Ahtenberg | last post: by
1 post views Thread by inderjit S Gabrie | last post: by
2 posts views Thread by Jack | last post: by
3 posts views Thread by Sandwick | last post: by
3 posts views Thread by gieforce | last post: by
reply views Thread by theflame83 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.