Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #24852 > unrolled thread

2D arrays, pointers, and pointer arithmetic: question

Started bygdotone@gmail.com
First post2012-08-24 08:28 -0700
Last post2012-09-07 06:28 -0700
Articles 20 on this page of 33 — 17 participants

Back to article view | Back to comp.lang.c


Contents

  2D arrays, pointers, and pointer arithmetic: question gdotone@gmail.com - 2012-08-24 08:28 -0700
    Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <adrian.ratnapala@gmail.com> - 2012-08-24 08:41 -0700
    Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-24 12:01 -0400
      Re: 2D arrays, pointers, and pointer arithmetic: question 88888 Dihedral <dihedral88888@googlemail.com> - 2012-08-24 11:10 -0700
    Re: 2D arrays, pointers, and pointer arithmetic: question gdotone@gmail.com - 2012-08-27 13:35 -0700
      Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-27 16:46 -0400
        Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <raka@scooter.fritz.box> - 2012-08-28 19:06 +0000
          Re: 2D arrays, pointers, and pointer arithmetic: question Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-08-28 15:22 -0400
          Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-28 15:34 -0400
            Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-28 14:11 -0700
              Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-28 17:26 -0400
              Re: 2D arrays, pointers, and pointer arithmetic: question "io_x" <a@b.c.invalid> - 2012-08-29 09:25 +0200
            Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <raka@scooter.fritz.box> - 2012-08-29 07:20 +0000
              Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-29 07:17 -0400
                Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <raka@scooter.fritz.box> - 2012-08-29 11:41 +0000
              Re: 2D arrays, pointers, and pointer arithmetic: question Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-08-29 08:21 -0400
                Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-29 11:37 -0700
                  Re: 2D arrays, pointers, and pointer arithmetic: question Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> - 2012-08-29 20:05 +0000
                    Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-29 17:27 -0400
                    Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-29 18:05 -0700
                      Re: 2D arrays, pointers, and pointer arithmetic: question Les Cargill <lcargill99@comcast.com> - 2012-08-29 20:14 -0500
                        Re: 2D arrays, pointers, and pointer arithmetic: question Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-08-30 04:47 -0700
                          Re: 2D arrays, pointers, and pointer arithmetic: question Richard Damon <news.x.richarddamon@xoxy.net> - 2012-09-01 23:47 -0400
                            Re: 2D arrays, pointers, and pointer arithmetic: question 88888 Dihedral <dihedral88888@googlemail.com> - 2012-09-02 04:43 -0700
                              Re: 2D arrays, pointers, and pointer arithmetic: question Richard Damon <news.x.richarddamon@xoxy.net> - 2012-09-02 23:12 -0400
                      Re: 2D arrays, pointers, and pointer arithmetic: question ais523 <ais523@nethack4.org> - 2012-08-30 11:35 +0000
                  Re: 2D arrays, pointers, and pointer arithmetic: question ralph <nt_consulting64@yahoo.com> - 2012-08-30 11:17 -0500
                    Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-30 13:52 -0700
                      Re: 2D arrays, pointers, and pointer arithmetic: question Anders Wegge Keller <wegge@wegge.dk> - 2012-08-30 23:13 +0200
                      Re: 2D arrays, pointers, and pointer arithmetic: question ralph <nt_consulting64@yahoo.com> - 2012-08-31 16:37 -0500
      Re: 2D arrays, pointers, and pointer arithmetic: question Barry Schwarz <schwarzb@dqel.com> - 2012-08-27 19:45 -0700
        Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-27 20:40 -0700
          Re: 2D arrays, pointers, and pointer arithmetic: question Tim Rentsch <txr@alumni.caltech.edu> - 2012-09-07 06:28 -0700

Page 1 of 2  [1] 2  Next page →


#24852 — 2D arrays, pointers, and pointer arithmetic: question

Fromgdotone@gmail.com
Date2012-08-24 08:28 -0700
Subject2D arrays, pointers, and pointer arithmetic: question
Message-ID<e03d454c-bb78-4a20-be1a-9d082c7e1748@googlegroups.com>
I'm reading "A Book on C", 4th edition. The author gives the following example when discussing two dimensional arrays:

a[3][5], so let a[][] be of type int.


           col 1        col 2      col 3       col 4      col 5
row 1     a[0][0]     a[0][1]     a[0][2]     a[0][3]    a[0][4]
row 2     a[1][0]     a[1][1]     a[1][2]     a[1][3]    a[1][4]
row 3     a[2][0]     a[2][1]     a[2][2]     a[2][3]    a[2][4]

The author then says that the following expression are equivalent

a[i][j]
*(a[i] + j)
(*(a + i))[j]
*((*(a+i)) + j)
*(&a[0][0] + 5*i + j)

I understand that the table is just a convenient representation of the 2D array.
In memory the 2D array is actually contiguous. OK. 

My question has to do with saying or writing out in words what is being shown when using the *, dereferencing, and &, address operators.

Is this the correct way of saying:

*(a[i] + j) the base address is pointed to by a[i] and we move along the contiguous memory j (interval), so we add j, j of size int, to get the value at that location we use the dereference operator.

I believe I understand what's happening, but am I saying it right.

(*(a + i))[j] the base address is at a, i is added to the base address, ok, I understand that we are looking at the row location here, but I'm stuck at how to say this.

let's say addresses are given in decimal, an integer in one byte and each address points to a byte. I hope I'm saying this right?
at address 100, a[0][0]
at address 109, a[1][0]
(if this thought is wrong please clear this up)

let's also say we are starting at location 100 (decimal).
consider a[1][0]. row 2, col 1 for the following discussion please.

(*(a + i ))[j] --- (*(a + 1))[0]
so, a, the start of the array is pointing to location 100
What does it mean to add 1 to a?
I mean, I understand that we are now at the address of the second row. I guess this should be known from the additional [0] indicating this is not just a one byte move? 

And what about the others like: *((*(a+i)) + j)
Let me stop here, I think I'm starting to confuse myself. (ok, yes i'm already confused. :-)  )

Thanks for the help everyone,

g.

[toc] | [next] | [standalone]


#24853

FromAdrian Ratnapala <adrian.ratnapala@gmail.com>
Date2012-08-24 08:41 -0700
Message-ID<d5883ba8-ca28-4182-95c6-67e146226a0a@googlegroups.com>
In reply to#24852
 
> *(a[i] + j) the base address is pointed to by a[i] and we move along the 

Yes, but that makes a[i] sound like a pointer.  I would say "a[i], is the i'th element of a 2d array, which is therefore a 1-d array".  


> contiguous memory j (interval), so we add j, j of size int, to get the 
> value at that location we use the dereference operator.

I would say "we then implicitly convert a[i] to a pointer-to-int, add j and then dereference it".  Which I think is what you said.

 
> (*(a + i))[j] the base address is at a, i is added to the base address, ok, I

"Implicitly convert `a` into a pointer-to-array-of-ints", add `i` to it (which means increment the pointer by 3*sizeof(int) bytes).  Then get an array-of-ints by dereferencing that pointer (this step doesn't do an actual memory lookup, it just changes the type; arrays are weird that way).  Finally give us the j'th integer in that array.


I'll stop now, because I am supposed to be doing real work.  I hope it helps.

[toc] | [prev] | [next] | [standalone]


#24855

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-08-24 12:01 -0400
Message-ID<5037A576.6020506@verizon.net>
In reply to#24852
On 08/24/2012 11:28 AM, gdotone@gmail.com wrote:
> I'm reading "A Book on C", 4th edition. The author gives the following example when discussing two dimensional arrays:
> 
> a[3][5], so let a[][] be of type int.
> 
> 
>            col 1        col 2      col 3       col 4      col 5
> row 1     a[0][0]     a[0][1]     a[0][2]     a[0][3]    a[0][4]
> row 2     a[1][0]     a[1][1]     a[1][2]     a[1][3]    a[1][4]
> row 3     a[2][0]     a[2][1]     a[2][2]     a[2][3]    a[2][4]
> 
> The author then says that the following expression are equivalent
> 
> a[i][j]
> *(a[i] + j)
> (*(a + i))[j]
> *((*(a+i)) + j)
> *(&a[0][0] + 5*i + j)

<pedantic>
This last expression takes a pointer to the first element of an array
containing only 5 elements, and (for i > 0) attempts to dereference it
after adding an integer greater than or equal to 5. Such derefencing has
undefined behavior (6.5.6p8). This interpretation of the standard is
controversial, but IMNSHO correct. In practice, on many machines it will
work exactly as expected. It's unlikely to fail except on systems which
provide run-time array bounds checking, which is rare.

Otherwise, the only way it's likely to fail is if the optimizer takes
advantage of the fact that it has undefined behavior by performing
optimizations that depend upon such code not being executed. For
instance, an implementation that performs an optimization based upon the
assumption that a[0]+i never refers to the same object a[1]+j,
regardless of the values of i and j, is perfectly legal despite the fact
that such an optimization could break code like this.
</pedantic>

> I understand that the table is just a convenient representation of the 2D array.
> In memory the 2D array is actually contiguous. OK. 
> 
> My question has to do with saying or writing out in words what is being shown when using the *, dereferencing, and &, address operators.
> 
> Is this the correct way of saying:
> 
> *(a[i] + j) the base address is pointed to by a[i] and we move along the contiguous memory j (interval), so we add j, j of size int, to get the value at that location we use the dereference operator.
> 
> I believe I understand what's happening, but am I saying it right.

Not quite, a[i] doesn't point at the base address. a[i] is an expression
of array type, and in most contexts (this being one of them) gets
automatically converted to a pointer (address) to the first element of
the array.

> (*(a + i))[j] the base address is at a, i is added to the base address, ok, I understand that we are looking at the row location here, but I'm stuck at how to say this.

a is an expression of array type, which automatically gets converted
into a pointer to the first element of that array, a[0]. Adding 'i' to
that pointer gives the address of the 'i+1'th element of that array,
a[i]. Dereferencing that pointer gives an expression of array type,
referring to a[i]. Like all such expressions, in most contexts, it gets
automatically converted to a pointer to the first element of that array
a[i][0]. Whenever x[j] is a valid expression, it is equivalent to
*(x+j). Adding 'j' to that pointer gives a pointer to the 'j+1'th
element of a[i], which is a[i][j]. Dereferencing that pointer gives the
value of that element.

> let's say addresses are given in decimal, an integer in one byte and each address points to a byte. I hope I'm saying this right?
> at address 100, a[0][0]
> at address 109, a[1][0]
> (if this thought is wrong please clear this up)

a[1][0] is stored at a position that is exactly 5*sizeof a[0][0] bytes
after the position of a[0][0]. Therefore, assuming a linear address
space (which C does NOT require), the difference in the addresses must
be an exact multiple of 5. 109-100=9 doesn't qualify.

> let's also say we are starting at location 100 (decimal).
> consider a[1][0]. row 2, col 1 for the following discussion please.
> 
> (*(a + i ))[j] --- (*(a + 1))[0]
> so, a, the start of the array is pointing to location 100
> What does it mean to add 1 to a?

a + 1 => &a[0] + 1 => &a[1].

[toc] | [prev] | [next] | [standalone]


#24865

From88888 Dihedral <dihedral88888@googlemail.com>
Date2012-08-24 11:10 -0700
Message-ID<179c8d68-2724-4cc5-90fc-e97cfc3eee97@googlegroups.com>
In reply to#24855
James Kuyper於 2012年8月25日星期六UTC+8上午12時01分58秒寫道:
> On 08/24/2012 11:28 AM, gdotone@gmail.com wrote:
> 
> > I'm reading "A Book on C", 4th edition. The author gives the following example when discussing two dimensional arrays:
> 
> > 
> 
> > a[3][5], so let a[][] be of type int.
> 
> > 
> 
> > 
> 
> >            col 1        col 2      col 3       col 4      col 5
> 
> > row 1     a[0][0]     a[0][1]     a[0][2]     a[0][3]    a[0][4]
> 
> > row 2     a[1][0]     a[1][1]     a[1][2]     a[1][3]    a[1][4]
> 
> > row 3     a[2][0]     a[2][1]     a[2][2]     a[2][3]    a[2][4]
> 
> > 
> 
> > The author then says that the following expression are equivalent
> 
> > 
> 
> > a[i][j]
> 
> > *(a[i] + j)
> 
> > (*(a + i))[j]
> 
> > *((*(a+i)) + j)
> 
> > *(&a[0][0] + 5*i + j)
> 
> 
> 
> <pedantic>
> 
> This last expression takes a pointer to the first element of an array
> 
> containing only 5 elements, and (for i > 0) attempts to dereference it
> 
> after adding an integer greater than or equal to 5. Such derefencing has
> 
> undefined behavior (6.5.6p8). This interpretation of the standard is
> 
> controversial, but IMNSHO correct. In practice, on many machines it will
> 
> work exactly as expected. It's unlikely to fail except on systems which
> 
> provide run-time array bounds checking, which is rare.
> 
> 
> 
> Otherwise, the only way it's likely to fail is if the optimizer takes
> 
> advantage of the fact that it has undefined behavior by performing
> 
> optimizations that depend upon such code not being executed. For
> 
> instance, an implementation that performs an optimization based upon the
> 
> assumption that a[0]+i never refers to the same object a[1]+j,
> 
> regardless of the values of i and j, is perfectly legal despite the fact
> 
> that such an optimization could break code like this.
> 
> </pedantic>
> 
> 
> 
> > I understand that the table is just a convenient representation of the 2D array.
> 
> > In memory the 2D array is actually contiguous. OK. 
> 
> > 
> 
> > My question has to do with saying or writing out in words what is being shown when using the *, dereferencing, and &, address operators.
> 
> > 
> 
> > Is this the correct way of saying:
> 
> > 
> 
> > *(a[i] + j) the base address is pointed to by a[i] and we move along the contiguous memory j (interval), so we add j, j of size int, to get the value at that location we use the dereference operator.
> 
> > 
> 
> > I believe I understand what's happening, but am I saying it right.
> 
> 
> 
> Not quite, a[i] doesn't point at the base address. a[i] is an expression
> 
> of array type, and in most contexts (this being one of them) gets
> 
> automatically converted to a pointer (address) to the first element of
> 
> the array.
> 
> 
> 
> > (*(a + i))[j] the base address is at a, i is added to the base address, ok, I understand that we are looking at the row location here, but I'm stuck at how to say this.
> 
> 
> 
> a is an expression of array type, which automatically gets converted
> 
> into a pointer to the first element of that array, a[0]. Adding 'i' to
> 
> that pointer gives the address of the 'i+1'th element of that array,
> 
> a[i]. Dereferencing that pointer gives an expression of array type,
> 
> referring to a[i]. Like all such expressions, in most contexts, it gets
> 
> automatically converted to a pointer to the first element of that array
> 
> a[i][0]. Whenever x[j] is a valid expression, it is equivalent to
> 
> *(x+j). Adding 'j' to that pointer gives a pointer to the 'j+1'th
> 
> element of a[i], which is a[i][j]. Dereferencing that pointer gives the
> 
> value of that element.
> 
> 
> 
> > let's say addresses are given in decimal, an integer in one byte and each address points to a byte. I hope I'm saying this right?
> 
> > at address 100, a[0][0]
> 
> > at address 109, a[1][0]
> 
> > (if this thought is wrong please clear this up)
> 
> 
> 
> a[1][0] is stored at a position that is exactly 5*sizeof a[0][0] bytes
> 
> after the position of a[0][0]. Therefore, assuming a linear address
> 
> space (which C does NOT require), the difference in the addresses must
> 
> be an exact multiple of 5. 109-100=9 doesn't qualify.
> 
> 
> 
> > let's also say we are starting at location 100 (decimal).
> 
> > consider a[1][0]. row 2, col 1 for the following discussion please.
> 
> > 
> 
> > (*(a + i ))[j] --- (*(a + 1))[0]
> 
> > so, a, the start of the array is pointing to location 100
> 
> > What does it mean to add 1 to a?
> 
> 
> 
> a + 1 => &a[0] + 1 => &a[1].

In summary one should view int ** a, and int *a2[4000], and int a3[4000][4000]
differently.

The last one has been very  easy to be used in the unix or linux
 systems long time ago.

[toc] | [prev] | [next] | [standalone]


#25134

Fromgdotone@gmail.com
Date2012-08-27 13:35 -0700
Message-ID<17a940de-ace8-4536-b8ac-e65366328836@googlegroups.com>
In reply to#24852

Again thanks everyone.

I think have a better understanding of what is happening and what the other expressions are doing and how to describe them.

I created a simple program, creating a 2X3 array and explored the address of the expressions, in piece and whole.

#include <stdio.h>
#include <stdlib.h>

#define SPACE_BETWEEN_LINES "\n\n"

int main(void)
{
   int a[2][3];
   int i,j;

   printf ( SPACE_BETWEEN_LINES );

   for ( i = 0; i < 2; i++ )
      for ( j = 0; j < 3; j++ )
         a[i][j] = 0;
   
   printf ( SPACE_BETWEEN_LINES );

   for ( i = 0; i < 2; i++ )
      for ( j = 0; j < 3; j++ )
         printf ( "The address for a[%d][%d] is   %p\n", i, j, &a[i][j] ); 

   printf ( SPACE_BETWEEN_LINES );

   for ( i = 0; i < 2; i++ )
      for ( j = 0; j < 3; j++ )
         printf ( "The address for ((*(a + %d)) + %d) is  %p\n",
                      i, j, ((*(a+i)) +j) );

   printf ( SPACE_BETWEEN_LINES ); 

   printf ( "The starting address of a is:     %p\n\n", a );

   printf ( "The second row starting address:  %p\n\n", a + 1 );
   
   printf ( "The a[1][0] address is :          %p\n\n", &a[1][0] );

   printf ( SPACE_BETWEEN_LINES );

   printf ( "*(a+0) address is:          %p\n\n", *(a+0) );

   printf ( "*(a+0) + 1 address is:      %p\n", *(a+0) + 1);

   printf ( "The value at *(a+0) is %d\n", **(a+0) ); /*   *(*(a+0))    */

   printf ( "\n" ); 

   return 1;
}

Output:


The address for a[0][0] is   0x7fff67ca8bf0
The address for a[0][1] is   0x7fff67ca8bf4
The address for a[0][2] is   0x7fff67ca8bf8
The address for a[1][0] is   0x7fff67ca8bfc
The address for a[1][1] is   0x7fff67ca8c00
The address for a[1][2] is   0x7fff67ca8c04


The address for ((*(a + 0)) + 0) is  0x7fff67ca8bf0
The address for ((*(a + 0)) + 1) is  0x7fff67ca8bf4
The address for ((*(a + 0)) + 2) is  0x7fff67ca8bf8
The address for ((*(a + 1)) + 0) is  0x7fff67ca8bfc
The address for ((*(a + 1)) + 1) is  0x7fff67ca8c00
The address for ((*(a + 1)) + 2) is  0x7fff67ca8c04


The starting address of a is:     0x7fff67ca8bf0

The second row starting address:  0x7fff67ca8bfc

The a[1][0] address is :          0x7fff67ca8bfc



*(a+0) address is:          0x7fff67ca8bf0

*(a+0) + 1 address is:      0x7fff67ca8bf4
The value at *(a+0) is 0

Ok, *(a+0) returns and address, *(a+0) + 1 returns an address.

So, given a[][], a two dimensional array, *(a+i) will return the address of the starting row, *(a+i) + j, returns the address of row,column, &a[i][j]. 
The i term added to a is being added to the base address of the array and itself, i, representing the size of a row. j then adds to that address giving the column position.  

Or something like that... :-) 

Thanks again.


[toc] | [prev] | [next] | [standalone]


#25135

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-08-27 16:46 -0400
Message-ID<503BDC9D.9080008@verizon.net>
In reply to#25134
On 08/27/2012 04:35 PM, gdotone@gmail.com wrote:
...
>          printf ( "The address for a[%d][%d] is   %p\n", i, j, &a[i][j] );

Whenever you print a pointer using "%p", the expression you print should
have the type 'void*'. In all cases in this code, that would require a
cast: (void*). Your code appears to work as expected, because on your
system, as on many others, the conversion to void* is a no-op for these
pointer types. However there are systems where such code won't work as
expected without the cast; it might not work at all, causing your
program to fail.
I didn't notice any other problems with your code, and your description
of what you're expecting to see seems to match the standard (assuming a
linear address space - which is very common, but NOT required).

[toc] | [prev] | [next] | [standalone]


#25281

FromAdrian Ratnapala <raka@scooter.fritz.box>
Date2012-08-28 19:06 +0000
Message-ID<slrnk3q5lp.2lr.raka@scooter.fritz.box>
In reply to#25135
On 2012-08-27, James Kuyper <jameskuyper@verizon.net> wrote:
> On 08/27/2012 04:35 PM, gdotone@gmail.com wrote:
> ...
>>          printf ( "The address for a[%d][%d] is   %p\n", i, j, &a[i][j] );
>
> Whenever you print a pointer using "%p", the expression you print should
> have the type 'void*'. In all cases in this code, that would require a

Is there really any reason to cast an (int *) into a (void *).  The only
reason I could imagine is to keep your compiler quiet.

[toc] | [prev] | [next] | [standalone]


#25286

FromEric Sosman <esosman@ieee-dot-org.invalid>
Date2012-08-28 15:22 -0400
Message-ID<k1j5p6$jr2$1@dont-email.me>
In reply to#25281
On 8/28/2012 3:06 PM, Adrian Ratnapala wrote:
> On 2012-08-27, James Kuyper <jameskuyper@verizon.net> wrote:
>> On 08/27/2012 04:35 PM, gdotone@gmail.com wrote:
>> ...
>>>           printf ( "The address for a[%d][%d] is   %p\n", i, j, &a[i][j] );
>>
>> Whenever you print a pointer using "%p", the expression you print should
>> have the type 'void*'. In all cases in this code, that would require a
>
> Is there really any reason to cast an (int *) into a (void *).  The only
> reason I could imagine is to keep your compiler quiet.

     This is Question 5.17 at the comp.lang.c Frequently Asked
Questions (FAQ) page, <http://www.c-faq.com/>.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid

[toc] | [prev] | [next] | [standalone]


#25289

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-08-28 15:34 -0400
Message-ID<503D1D4C.6060505@verizon.net>
In reply to#25281
On 08/28/2012 03:06 PM, Adrian Ratnapala wrote:
> On 2012-08-27, James Kuyper <jameskuyper@verizon.net> wrote:
>> On 08/27/2012 04:35 PM, gdotone@gmail.com wrote:
>> ...
>>>          printf ( "The address for a[%d][%d] is   %p\n", i, j, &a[i][j] );
>>
>> Whenever you print a pointer using "%p", the expression you print should
>> have the type 'void*'. In all cases in this code, that would require a
> 
> Is there really any reason to cast an (int *) into a (void *).  The only
> reason I could imagine is to keep your compiler quiet.

The standard says that the behavior is undefined. It does so because
there are real platforms out there where void* is incompatible with
int*. For instance, on platforms where the word size is larger than than
a byte, a void* must include information identifying the particular byte
within a word where an object starts, because it might be required to
point at an object smaller than a word. However, for word-aligned types,
the pointer need only identify which word it starts at. There have been
real machines where pointers to word-aligned types have been smaller
than pointers to smaller types, for precisely this reason.
It's also permissible for pointers of the same size to use different
representations. I don't know of any examples, but I wouldn't recommend
ruling out that possibility.

Is that a good enough reason for you? If you're certain your code will
never be used on such machines, you can ignore the issue - in which case
someone, not necessarily you, will pay the price if your certainty turns
out to be unjustified. If you do this, you'll have plenty of company.

[toc] | [prev] | [next] | [standalone]


#25301

FromKeith Thompson <kst-u@mib.org>
Date2012-08-28 14:11 -0700
Message-ID<lnharmzpq0.fsf@nuthaus.mib.org>
In reply to#25289
James Kuyper <jameskuyper@verizon.net> writes:
> On 08/28/2012 03:06 PM, Adrian Ratnapala wrote:
[...]
>> Is there really any reason to cast an (int *) into a (void *).  The only
>> reason I could imagine is to keep your compiler quiet.
>
> The standard says that the behavior is undefined. It does so because
> there are real platforms out there where void* is incompatible with
> int*.
[...]

Strictly speaking, void* and int* are incompatible types regardless of
the platform (the standard has its own definition of compatibility for
types).  The point, of course, is that they can have different
representations.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#25306

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-08-28 17:26 -0400
Message-ID<503D378E.5020301@verizon.net>
In reply to#25301
On 08/28/2012 05:11 PM, Keith Thompson wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
>> On 08/28/2012 03:06 PM, Adrian Ratnapala wrote:
> [...]
>>> Is there really any reason to cast an (int *) into a (void *).  The only
>>> reason I could imagine is to keep your compiler quiet.
>>
>> The standard says that the behavior is undefined. It does so because
>> there are real platforms out there where void* is incompatible with
>> int*.
> [...]
> 
> Strictly speaking, void* and int* are incompatible types regardless of
> the platform (the standard has its own definition of compatibility for
> types).  The point, of course, is that they can have different
> representations.

I should have said "have incompatible representations". I didn't mean to
bring C's definition of compatible types into the discussion.
Incompatible representations is a sufficient, but not necessary,
condition for types to be incompatible.

[toc] | [prev] | [next] | [standalone]


#25355

From"io_x" <a@b.c.invalid>
Date2012-08-29 09:25 +0200
Message-ID<503dc275$0$17949$4fafbaef@reader1.news.tin.it>
In reply to#25301
"Keith Thompson" <kst-u@mib.org> ha scritto nel messaggio
news:lnharmzpq0.fsf@nuthaus.mib.org...
> James Kuyper <jameskuyper@verizon.net> writes:
>> On 08/28/2012 03:06 PM, Adrian Ratnapala wrote:
> [...]
>>> Is there really any reason to cast an (int *) into a (void *).  The only
>>> reason I could imagine is to keep your compiler quiet.
>>
>> The standard says that the behavior is undefined. It does so because
>> there are real platforms out there where void* is incompatible with
>> int*.
> [...]
>
> Strictly speaking, void* and int* are incompatible types regardless of
> the platform (the standard has its own definition of compatibility for
> types).  The point, of course, is that they can have different
> representations.

"void* and int* are incompatible types..." but
i would remember for standard would be ok
int  *p, *x, v=0, r;
void *pv;

p=&v; pv=p; x=pv; r=*x;
and r would be ==0==*&v


[toc] | [prev] | [next] | [standalone]


#25356

FromAdrian Ratnapala <raka@scooter.fritz.box>
Date2012-08-29 07:20 +0000
Message-ID<slrnk3rglh.1cj.raka@scooter.fritz.box>
In reply to#25289
In comp.lang.c, you wrote:
>>
>> Is there really any reason to cast an (int *) into a (void *).  The only
>> reason I could imagine is to keep your compiler quiet.
>
> The standard says that the behavior is undefined. It does so because
> there are real platforms out there where void* is incompatible with
> int*. For instance, on platforms where the word size is larger than than
<snip>

> Is that a good enough reason for you? If you're certain your code will
That's a good enough reason.

I had mistakenly thought the (void *) requirement was mere pedanticism,
because I thought pointers always had the same size unless explictly
modified by something like "near/far".  And I agree "always, on the
machines you know about is a far, far cry from "always".

BTW: I don't know if my misconception is "frequent" enough to warrant an
FAQ change, but it doesn't look like the FAQ covers this.  Contra Eric,
5.17 is about something else;  4.17 / 19.40 are closer but not quite
relevant.

[toc] | [prev] | [next] | [standalone]


#25370

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-08-29 07:17 -0400
Message-ID<k1ktog$nvu$1@dont-email.me>
In reply to#25356
On 08/29/2012 03:20 AM, Adrian Ratnapala wrote:
> In comp.lang.c, you wrote:
>>>
>>> Is there really any reason to cast an (int *) into a (void *).  The only
>>> reason I could imagine is to keep your compiler quiet.
>>
>> The standard says that the behavior is undefined. It does so because
>> there are real platforms out there where void* is incompatible with
>> int*. For instance, on platforms where the word size is larger than than
> <snip>
> 
>> Is that a good enough reason for you? If you're certain your code will
> That's a good enough reason.
> 
> I had mistakenly thought the (void *) requirement was mere pedanticism,

Almost every seemly pedantic issue associated with the standard exists
because there are implementations where the issue is relevant, or at
least there were such implementations at the time the rule was created.
There's a few that exist just because the committee didn't see any need
to impose a requirement on future implementations just because every
current implementation satisfies that requirement, but those are rare.

> because I thought pointers always had the same size unless explictly
> modified by something like "near/far". ...

In general, pointers to different types can, in principle, have
different representations, alignment requirements, or even sizes. The
word-size issue is the only one I'm aware of that actually comes up on
real implementations, but there's probably other reasons I'm unaware of.
There's only a few exceptions:

Pointers to void have the same representation and alignment requirements
as pointers to character types (6.2.5p268).

Identically-qualified pointers to compatible types are compatible
(6.7.6.1p2), and pointer types that differ only in the way that they are
qualified have the same representation and alignment (6.2.5p26).

> ... And I agree "always, on the
> machines you know about is a far, far cry from "always".

Good - I'd thought your comment reflected a more casual attitude toward
portability issues. The tone of my reply reflected my disdain for people
with such attitudes; I apologize for that.

> BTW: I don't know if my misconception is "frequent" enough to warrant an
> FAQ change, but it doesn't look like the FAQ covers this.  Contra Eric,
> 5.17 is about something else;

5.17 is also about other things, but it mentions systems which use
multiple different (and presumably incompatible) pointer types: the
Eclipse MV series from Data General, the HP 3000, "several of the
machines above" (which is a little vague), and some 64-bit Cray
machines. All three of the specific example involve word pointers vs.
byte pointers.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#25374

FromAdrian Ratnapala <raka@scooter.fritz.box>
Date2012-08-29 11:41 +0000
Message-ID<slrnk3rvuu.3jo.raka@scooter.fritz.box>
In reply to#25370
>> BTW: I don't know if my misconception is "frequent" enough to warrant an
>> FAQ change, but it doesn't look like the FAQ covers this.  Contra Eric,
>> 5.17 is about something else;
>
> 5.17 is also about other things, but it mentions systems which use
> multiple different (and presumably incompatible) pointer types: the

All true, but it doesn't directly tackle my error, only the consequences
of it.  That's fine in an FAQ, since it could be that many people are
confused about NULL pointers while not so many have specific wrong ideas
about pointer representations.

On the other hand, if my error *is* common.  Or at least if people often
ask that turn out to involve pointer representations, then the FAQ
should probably include something similar to what you just wrote.

[toc] | [prev] | [next] | [standalone]


#25378

FromEric Sosman <esosman@ieee-dot-org.invalid>
Date2012-08-29 08:21 -0400
Message-ID<k1l1gb$e34$1@dont-email.me>
In reply to#25356
On 8/29/2012 3:20 AM, Adrian Ratnapala wrote:
> [... about converting int* to void* for "%p" conversion ...]
> BTW: I don't know if my misconception is "frequent" enough to warrant an
> FAQ change, but it doesn't look like the FAQ covers this.  Contra Eric,
> 5.17 is about something else;  4.17 / 19.40 are closer but not quite
> relevant.

     5.17 is mostly about representations of null pointers, but
not entirely.  If you'll read the entire thing, you'll find two
specific mentions of different pointer formats, plus a link to
further examples.

     14.17 and 19.40(d) are about `near' and `far', whose
connection to the matter at hand eludes me.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid

[toc] | [prev] | [next] | [standalone]


#25414

FromKeith Thompson <kst-u@mib.org>
Date2012-08-29 11:37 -0700
Message-ID<lnbohty27l.fsf@nuthaus.mib.org>
In reply to#25378
Eric Sosman <esosman@ieee-dot-org.invalid> writes:
> On 8/29/2012 3:20 AM, Adrian Ratnapala wrote:
>> [... about converting int* to void* for "%p" conversion ...]
>> BTW: I don't know if my misconception is "frequent" enough to warrant an
>> FAQ change, but it doesn't look like the FAQ covers this.  Contra Eric,
>> 5.17 is about something else;  4.17 / 19.40 are closer but not quite
>> relevant.
>
>      5.17 is mostly about representations of null pointers, but
> not entirely.  If you'll read the entire thing, you'll find two
> specific mentions of different pointer formats, plus a link to
> further examples.
>
>      14.17 and 19.40(d) are about `near' and `far', whose
> connection to the matter at hand eludes me.

`near` and `far`, which are of course non-standard, can result in
different pointer types having different sizes.  Passing a `near`
or `far` pointer to printf with a "%p" format is likely to give
bad results in practice.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#25437

FromEdward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com>
Date2012-08-29 20:05 +0000
Message-ID<k1lsli$7gd$1@speranza.aioe.org>
In reply to#25414
Keith Thompson wrote:
> `near` and `far`, which are of course non-standard, can result in
> different pointer types having different sizes.  Passing a `near` or
> `far` pointer to printf with a "%p" format is likely to give bad results
> in practice.

Using near or far pointers in any way at all will invoke an undefined 
behavior, so I think it's safe to say bad results are likely with or 
without attempts to printf() such pointers!

[toc] | [prev] | [next] | [standalone]


#25452

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-08-29 17:27 -0400
Message-ID<503E8943.1010908@verizon.net>
In reply to#25437
On 08/29/2012 04:05 PM, Edward Rutherford wrote:
> Keith Thompson wrote:
>> `near` and `far`, which are of course non-standard, can result in
>> different pointer types having different sizes.  Passing a `near` or
>> `far` pointer to printf with a "%p" format is likely to give bad results
>> in practice.
> 
> Using near or far pointers in any way at all will invoke an undefined 
> behavior, so I think it's safe to say bad results are likely with or 
> without attempts to printf() such pointers!

Within the context of the C standard, "undefined behavior" means only
that the C standard doesn't define the behavior. If the compiler's
documentation does define the behavior, you should be OK, even if the C
standard doesn't.

However, it's extremely unlikely that a compiler which supports both
near and far pointers would come along with a C standard library who's
printf() allows you to print both types of pointers with the same "%p"
format specifier. That's the "bad results in practice" that he was
talking about.

[toc] | [prev] | [next] | [standalone]


#25471

FromKeith Thompson <kst-u@mib.org>
Date2012-08-29 18:05 -0700
Message-ID<lnd329w5nq.fsf@nuthaus.mib.org>
In reply to#25437
Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes:
> Keith Thompson wrote:
>> `near` and `far`, which are of course non-standard, can result in
>> different pointer types having different sizes.  Passing a `near` or
>> `far` pointer to printf with a "%p" format is likely to give bad results
>> in practice.
>
> Using near or far pointers in any way at all will invoke an undefined 
> behavior, so I think it's safe to say bad results are likely with or 
> without attempts to printf() such pointers!

For a C implementation that supports `near`, `far`, `void*`, and
printf's "%p" format, I would expect that casting a `near` or `far`
pointer value to `void*` before passing it to printf would work
"correctly".  Of course the standard doesn't guarantee that, but I'd
expect it of any decent C or C-like implementation.

(I've never used `near` or `far` myself.  It's plausible that an
implementation old enough to support them would be too old to support
`void*`.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web