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


Groups > comp.lang.c > #5791

Re: pointer = &membuff[-2];

From James Kuyper <jameskuyper@verizon.net>
Newsgroups comp.lang.c
Subject Re: pointer = &membuff[-2];
Date 2011-06-10 08:23 -0400
Organization A noiseless patient Spider
Message-ID <ist2c3$mph$1@dont-email.me> (permalink)
References <isrcm7$q94$1@speranza.aioe.org>

Show all headers | View raw


On 06/09/2011 05:07 PM, Bo S. wrote:
> Is it possible to post a basic C question in this newsgroup without
> starting a flame war about "elegant" code or see answers like
> "silly, nonportable hack"? I've almost stopped reading this ng since
> there are usually more than 500 posts every day and most of it is
> opinons and comments on other's opinion.
> 
> Anyway, I take a chance: I have stripped out a piece of code that
> we have in a large application that in some circumstances will do
> what this example program show. The interesting part is the
> 
> pointer = &buffer[-2]; /* is it really -2, or 4294967294 */

It is really -2.

> x = pointer->data;     /* Reading something >2 unsigned's down */
> 
> It (seems to) work, I'm just wondering if we're lucky or not.

Code like this can work, though it does not work in your example below.
You could make it work by preceding it with code like the following:

	struct databin{
	    int other;
	    int data;
	} *full = malloc(10 * sizeof *full);

	if(full)
	{
	    struct databin *buffer = full + 2;
	    struct databin *pointer;

> I would appreciate if anyone can explain why, or why not, without
> arguing about good or bad programming style (this code has already
> been redesigned but exists alive and well in older versions of
> our product).
> 
> I guess buffer[-2] can be written *(buffer-2) and &buffer[-2]
> will simply be (buffer-2) and pointer->data will access memory
> at, say, (buffer-2)+2. But isn't n1-n2 = 4294967294 in the
> example below? Ok, 4294967294+2 is 0...or?
> 
> Here's an example program:
> 
> #define _POSIX_SOURCE 1
> #include <stdlib.h>
> #include <stdio.h>
> 
> signed int
> main(signed int argc, char ** argv)

The "signed" keyword is needed only for 'signed char'; its use with
other integer types is permitted, but has no effect, because those types
are already signed (unless you also use the "unsigned" keyword, in which
case adding "signed" would create a syntax error).

> {
>   unsigned int n1 = 0;
>   unsigned int n2 = 2;
>   unsigned int n3;
>   unsigned int *membuff;
>   struct dummy {
>       unsigned int d1;
>       unsigned int d2;
>       unsigned int d3;
>   } *sp;
> 
>   membuff = malloc(10*sizeof(unsigned int));

Better:
	membuff = malloc(10 * sizeof *membuff);

>   membuff[0] = 54;
> 
>   sp = (struct dummy *) &membuff[n1 - n2];

Yes, n1-n2 is UINT_MAX-1, not -2, as you suggest above. This gives this
code undefined behavior. Note, however, that the behavior would be
undefined, for essentially the same reason, if n1 and n2 were signed, so
that n1-n2 is -2. The only values you can safely put in that subscript
are 0 through 10. 10 is safe only because of the '&' - any other use of
memcpy[10] would have undefined behavior.

You don't have to dereference the resulting pointer to have problems,
and dereferencing it only to access sp->d3 doesn't avoid the problems.
The expression &membuf[-2] is equivalent to membuf-2, and it has
undefined behavior all by itself, before it's value is even converted to
(struct dummy *). On many real-world implementations, membuf-2 could be
an invalid pointer value, which means that even storing it in an address
register (as might be done somewhere in that expression) could cause
your program to abort or a signal to be raised (among many other
possibilities).

As a further, minor quibble, it's possible (though rather unlikely) that
the alignment requirements of struct dummy are stricter than those of
unsigned int, so it's not guaranteed that you could, for instance, even
safely cast (struct dummy*) &membuf[2].

If your code actually works, despite these problems, that's merely an
unfortunate coincidence. You'd have been better off if it had failed,
forcing you to fix these defects.
-- 
James Kuyper

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

pointer = &membuff[-2]; "Bo S." <bo@boo.invalid> - 2011-06-09 21:07 +0000
  Re: pointer = &membuff[-2]; Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2011-06-09 16:47 -0600
    Re: pointer = &membuff[-2]; BGB <cr88192@hotmail.com> - 2011-06-09 22:59 -0700
    Re: pointer = &membuff[-2]; pete <pfiland@mindspring.com> - 2011-06-10 06:28 -0400
  Re: pointer = &membuff[-2]; Keith Thompson <kst-u@mib.org> - 2011-06-09 17:54 -0700
    Re: pointer = &membuff[-2]; Noob <root@127.0.0.1> - 2011-06-10 13:03 +0200
      Re: pointer = &membuff[-2]; Keith Thompson <kst-u@mib.org> - 2011-06-10 08:10 -0700
    Re: pointer = &membuff[-2]; Keith Thompson <kst-u@mib.org> - 2011-06-10 08:12 -0700
  Re: pointer = &membuff[-2]; Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-06-09 21:02 -0400
  Re: pointer = &membuff[-2]; James Kuyper <jameskuyper@verizon.net> - 2011-06-09 22:25 -0400
  Re: pointer = &membuff[-2]; Shao Miller <sha0.miller@gmail.com> - 2011-06-10 01:10 -0500
    Re: pointer = &membuff[-2]; Shao Miller <sha0.miller@gmail.com> - 2011-06-10 01:13 -0500
      Re: pointer = &membuff[-2]; Shao Miller <sha0.miller@gmail.com> - 2011-06-10 01:20 -0500
  Re: pointer = &membuff[-2]; Shao Miller <sha0.miller@gmail.com> - 2011-06-10 03:33 -0500
  Re: pointer = &membuff[-2]; James Kuyper <jameskuyper@verizon.net> - 2011-06-10 08:23 -0400
  Re: pointer = &membuff[-2]; Sherm Pendley <sherm.pendley@gmail.com> - 2011-06-10 09:30 -0400
  Re: pointer = &membuff[-2]; ImpalerCore <jadill33@gmail.com> - 2011-06-10 07:15 -0700

csiph-web