pointer comparisons 
Author Message
 pointer comparisons

Hi there,

1st question (easy)

can a char * reference the byte past the '\0' in a string?

2nd question (extra credit)

having the following semi-pseudo snippet:

char *c = malloc(10 * sizeof *c);
int *i = malloc(10 * sizeof *i);
struct s *s = malloc(10 * sizeof *s);

iterate(c);
iterate(i);
iterate(s);

void iterate(anytype *p)
{
  for (anytype *pp = p; pp < p + 10; pp++)
    use(pp);

Quote:
}

I get the feeling that pointer comparison for at least one of the
three given anytype *'s is undefined, because here's what it says in
kazlib 1.20 (list.c:316):

/*
 * Determine whether the given pool is from this pool.
 */

int lnode_pool_isfrom(lnodepool_t *pool, lnode_t *node)
{
    listcount_t i;

    /* this is carefully coded this way because ANSI C forbids
pointers
       to different objects from being subtracted or compared other
       than for exact equality */

    for (i = 0; i < pool->size; i++) {
        if (pool->pool + i == node)
            return 1;
    }
    return 0;

Quote:
}

(I apologize iff these are not the same thing, but I'm equally
confused :))

On the other hand, char * comparisons are all to common that I'm
hesitating to think of them as invoking undefined behaviour :)

--
rihad



Sat, 26 Jun 2004 21:42:11 GMT  
 pointer comparisons

Quote:
> Hi there,
> 1st question (easy)
> can a char * reference the byte past the '\0' in a string?

I don't see why not. A pointer is allowed to point (but not
dereference) 1 byte past the end of an allocated space.

--

| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste       W++ B OP+                     |
\----------------------------------------- Finland rules! ------------/
"I am not very happy acting pleased whenever prominent scientists overmagnify
intellectual enlightenment."
   - Anon



Sat, 26 Jun 2004 21:53:12 GMT  
 pointer comparisons

Quote:

> 1st question (easy)

> can a char * reference the byte past the '\0' in a string?

If there's referable memory there, yes, why not? If there isn't, no, why
should it?
Note that it is always possible to _point_ one byte past the '\0',
because of the one-byte-past-a-memory-block rule; but it is only legal
to dereference that pointer if the block is larger than the string it
contains.
For example:

  char astr[7]="abcde";
  char bstr[6]="abcde";
  char *ptr;
  char chr;

  ptr=astr+6; /* Legal. */
  chr=*ptr; /* Dubious. Illegal only if a char can trap after all, but
               I'll assume it can't; which means chr now contains
               garbage, but legal garbage. */
  ptr=bstr+6; /* Legal. You're now pointing one past the array. */
  chr=*ptr; /* Illegal. You may point one beyond a memory block, but not
               read whatever may or may not be there. */

Quote:
> 2nd question (extra credit)

> having the following semi-pseudo snippet:

> char *c = malloc(10 * sizeof *c);
> int *i = malloc(10 * sizeof *i);
> struct s *s = malloc(10 * sizeof *s);

> iterate(c);
> iterate(i);
> iterate(s);

> void iterate(anytype *p)

What is anytype?

Quote:
> {
>   for (anytype *pp = p; pp < p + 10; pp++)
>     use(pp);
> }

> I get the feeling that pointer comparison for at least one of the
> three given anytype *'s is undefined,

Depends on what anytype is. If it's any kind of char, it's guaranteed to
be defined, as far as the pointer comparison goes. It's dubious practice
in any case, though, unless you figure out a way to tell iterate how
large your buffer is.

Richard



Sat, 26 Jun 2004 22:42:54 GMT  
 pointer comparisons

Quote:

>   char astr[7]="abcde";
>   char bstr[6]="abcde";
>   char *ptr;
>   char chr;

>   ptr=astr+6; /* Legal. */
>   chr=*ptr; /* Dubious. Illegal only if a char can trap after all, but
>                I'll assume it can't; which means chr now contains
>                garbage, but legal garbage. */

Doh. I initialised it. It contains '\0', guaranteed. So it's guaranteed
to be legal, too.
The comment in the quoted bit only goes if it's uninitialised memory
into which I've written "abcde", and no more, like this:

  char astr[7]; /* Assuming block scope. */
  strcpy(astr, "abcde");

Richard



Sat, 26 Jun 2004 22:46:08 GMT  
 pointer comparisons

Quote:


>>   char astr[7]="abcde";
>>   char bstr[6]="abcde";
>>   char *ptr;
>>   char chr;

>>   ptr=astr+6; /* Legal. */
>>   chr=*ptr; /* Dubious. Illegal only if a char can trap after all, but
>>                I'll assume it can't; which means chr now contains
>>                garbage, but legal garbage. */

>Doh. I initialised it. It contains '\0', guaranteed. So it's guaranteed
>to be legal, too.
>The comment in the quoted bit only goes if it's uninitialised memory
>into which I've written "abcde", and no more, like this:

>  char astr[7]; /* Assuming block scope. */
>  strcpy(astr, "abcde");

Or perhaps
char astr[7] = { 'a', 'b', 'c', 'd', 'e', 0 };

--
rihad



Sat, 26 Jun 2004 23:28:17 GMT  
 pointer comparisons

Quote:

>> char *c = malloc(10 * sizeof *c);
>> int *i = malloc(10 * sizeof *i);
>> struct s *s = malloc(10 * sizeof *s);

>> iterate(c);
>> iterate(i);
>> iterate(s);

>> void iterate(anytype *p)

>What is anytype?

It's pseudocode. Think of it as if I had explicitly written
iterate_{c, i, s} with the specific anytype. I thought it was obvious
from context, sorry.

Quote:
>> {
>>   for (anytype *pp = p; pp < p + 10; pp++)
>>     use(pp);
>> }

>> I get the feeling that pointer comparison for at least one of the
>> three given anytype *'s is undefined,

>Depends on what anytype is. If it's any kind of char, it's guaranteed to
>be defined, as far as the pointer comparison goes. It's dubious practice
>in any case, though, unless you figure out a way to tell iterate how
>large your buffer is.

I could have passed the '10' as an arg, that's not the point. Still,
why does it make a difference what p (and pp) point at? Is char
special? Aren't char, int, struct s all valid C objects? Can't pointer
arithmentic adn comparison work all of them with equal semantics?

--
rihad



Sat, 26 Jun 2004 23:33:35 GMT  
 pointer comparisons
Quote:
>>  char astr[7]; /* Assuming block scope. */
>>  strcpy(astr, "abcde");

>Or perhaps
>char astr[7] = { 'a', 'b', 'c', 'd', 'e', 0 };

Duh, sorry, it won't work, a mind glitch.

--
rihad



Sat, 26 Jun 2004 23:35:28 GMT  
 pointer comparisons


Quote:
> Hi there,

> 2nd question (extra credit)

> having the following semi-pseudo snippet:

> char *c = malloc(10 * sizeof *c);
> int *i = malloc(10 * sizeof *i);
> struct s *s = malloc(10 * sizeof *s);

> iterate(c);
> iterate(i);
> iterate(s);

> void iterate(anytype *p)
> {
>   for (anytype *pp = p; pp < p + 10; pp++)
>     use(pp);
> }

The problem is that there is no generic pointer type that you can increment.
C has a problem with this because a generic pointer type wouldn't have any
type information with it, and so it wouldn't know how far to increment the
pointer on a pp++, whether to the next char, int or struct s.  Here are two
ways to do it:

void iterate( void *p, size_t increment ) {
   int i;
   for (i=0; i<10; i++, p = (char*)p + increment) {
     use(p);
  }

Quote:
}

iterate( c, sizeof *c );
iterate( i, sizeof *i );
iterate( s, sizeof *s );

-- or --

#define iterate( p, type ) \
   do { \
      int i; \
      type pp = p; \
      for (i=0; i<10; i++, pp++) \
         use(pp); \
   }

iterate( c, char * );
iterate( i, int * );
iterate( s, struct s* );

(you can get rid of the type argument if you don't mind changing the value
of the first parameter).

--
poncho



Sat, 26 Jun 2004 23:58:30 GMT  
 pointer comparisons
On Tue, 8 Jan 2002 07:58:30 -0800, "Scott Fluhrer"
<snipped>
Since you're yet another poster after Richard Bos who misunderstood
the point of anytype * and iterate, I really ought to rethink my
conversational skills :) Sorry :)

The point was that whether having three functions

void iterate_c(char *p) { /* body stays same */ }
void iterate_i(int *p) { /* body stays same */ }
void iterate_s(struct s *p) { /* body stays same */ }

the pointer comparison (pp < p + 10) is legal in *all* of them. I have
reservations because of the aforeposted excerpt from kazlib.

--
rihad



Sun, 27 Jun 2004 00:16:43 GMT  
 pointer comparisons

Quote:

>Hi there,

>1st question (easy)

>can a char * reference the byte past the '\0' in a string?

After some thinking, I'm almost sure that it can, because a string can
really look like "hello\0world\0!\0", with a total of four '\0''s. It
all depends on how objects are laid out and undefined behaviour comes
into play when you access memory not belonging to the C virtual
machine. (thus, strlen((char *) 0xdeadbeef) is most likely undefined
even if it's well defined for an OS (like its version string being
there :)) Unless some part of a C object (of current program?) happens
to live at 0xdeadbeef.

--
rihad



Sun, 27 Jun 2004 00:37:07 GMT  
 pointer comparisons

Quote:

> Hi there,

> 1st question (easy)

> can a char * reference the byte past the '\0' in a string?

No.  Bytes past the '\0' are not defined for a string.  karl m


Sun, 27 Jun 2004 03:19:13 GMT  
 pointer comparisons

Quote:


> > can a char * reference the byte past the '\0' in a string?

> No.  Bytes past the '\0' are not defined for a string.  karl m

You are wrong as usual, Karl.  A pointer to one-past-the-end is
allowed for any object, and a string is no exception.
Dereferencing such a one-past-the-end pointer is not allowed.


Sun, 27 Jun 2004 03:22:52 GMT  
 pointer comparisons

Quote:

> On Tue, 8 Jan 2002 07:58:30 -0800, "Scott Fluhrer"

> <snipped>
> Since you're yet another poster after Richard Bos who misunderstood
> the point of anytype * and iterate, I really ought to rethink my
> conversational skills :) Sorry :)

> The point was that whether having three functions

> void iterate_c(char *p) { /* body stays same */ }
> void iterate_i(int *p) { /* body stays same */ }
> void iterate_s(struct s *p) { /* body stays same */ }

The body was:
{
  for (anytype *pp = p; pp < p + 10; pp++)
    use(pp);

Quote:
}

This is legal. The problem kaz lib tries to address is to figure
out if pointer sometype *p points into sometype array[X]; One
may be tempted to do

if(p>=array && p<array+X){
   /* p points into array */

Quote:
}else{

   /* p doesn't point into array */

Quote:
}

But this is illegal because in order to compare pointers with <, <= etc
they have to point to memory allocated for one and the same array in the
first place. That's why kazlib iterates over the elements of the array
and compares the pointer to each of these elements:

int i,into;
for(i=0,into=0;i<X && !into;tmp++)
    if(p==array+i)
        into=1;

if(into){
   /* p points into array */

Quote:
}else{

   /* p doesn't point into array */

Quote:
}

Tobias.


Sun, 27 Jun 2004 03:49:18 GMT  
 pointer comparisons

Quote:

>Hi there,

>1st question (easy)

>can a char * reference the byte past the '\0' in a string?

Yes. In C, a pointer which points to an array-like object can be
incremented to point to one element index beyond the end of that object.

That pointer is considered to point to the object for the purposes
of being compared to other pointers which are based on the same array.

That is to say, it's not wrong to use the relational operator to
compare this pointer to other pointers into the same array.

Only, it cannot be dereferenced to access anything.

Quote:
>2nd question (extra credit)

>having the following semi-pseudo snippet:

>char *c = malloc(10 * sizeof *c);
>int *i = malloc(10 * sizeof *i);
>struct s *s = malloc(10 * sizeof *s);

>iterate(c);
>iterate(i);
>iterate(s);

>void iterate(anytype *p)
>{
>  for (anytype *pp = p; pp < p + 10; pp++)
>    use(pp);
>}

This is in fact a common C idiom, and it is probably the primary reason
why pointer arithmetic is allowed to produce a pointer one past the end
of an array.  Without that provision, loop guards like pp < p + 10 would
risk nonportability. If p + 10 were not required to be a valid pointer
which compares greater than p or p + 9, the loop might not terminate.
That could happen if, say, the dynamic object were allocated at the
highest possible address in some memory segment, so that incrementing
one byte past its end would cause the pointer to wrap around.  The C
standard prhohibits such a behavior; the implementation has to leave at
least one byte of slack in such a situation.

Quote:
>I get the feeling that pointer comparison for at least one of the
>three given anytype *'s is undefined, because here's what it says in
>kazlib 1.20 (list.c:316):

That's a pretty roundabout way to learn obscure ANSI C facts, but I'm
glad someone finds it educational. ;)

Code has many uses; reading it, and even its comments, can be more
interesting than actually running it.



Sun, 27 Jun 2004 04:37:12 GMT  
 pointer comparisons

Quote:

> 1st question (easy)

> can a char * reference the byte past the '\0' in a string?

Of course.  a string is just an array of char with a '\0' marker.

Quote:

> 2nd question (extra credit)

> having the following semi-pseudo snippet:

> char *c = malloc(10 * sizeof *c);
> int *i = malloc(10 * sizeof *i);
> struct s *s = malloc(10 * sizeof *s);

> iterate(c);
> iterate(i);
> iterate(s);

> void iterate(anytype *p)
> {
>   for (anytype *pp = p; pp < p + 10; pp++)
>     use(pp);
> }

Assuming suitable coding based on the above pseudo template, why
not?  You are never creating pointers outside the allocated range
(+1), and never dereferencing any outside the range.  It might be
clearer with the exit condition written as "pp-p < 10".

--

   Available for consulting/temporary embedded and systems.
   (Remove "XXXX" from reply address. yahoo works unmodified)



Sun, 27 Jun 2004 08:08:44 GMT  
 
 [ 18 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Does pointer comparison cause undefined behaviour?

2. Null pointer comparisons

3. Pointer comparison with == and != valid?

4. Pointer comparisons 2

5. Pointer comparison legality?

6. Pointer comparison...start of array

7. rules of pointer comparison

8. Undefined Pointer Comparison

9. Pointer Comparison

10. pointer comparison

11. pointer comparison question

12. pointer comparison question

 

 
Powered by phpBB® Forum Software