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


Groups > comp.lang.c > #5769

Re: pointer = &membuff[-2];

From Keith Thompson <kst-u@mib.org>
Newsgroups comp.lang.c
Subject Re: pointer = &membuff[-2];
Date 2011-06-09 17:54 -0700
Organization None to speak of
Message-ID <ln8vtabj64.fsf@nuthaus.mib.org> (permalink)
References <isrcm7$q94$1@speranza.aioe.org>

Show all headers | View raw


"Bo S." <bo@boo.invalid> writes:
> 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 */
> x = pointer->data;     /* Reading something >2 unsigned's down */
>
> It (seems to) work, I'm just wondering if we're lucky or not.
> 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)
> {
>   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));
>   membuff[0] = 54;
>
>   sp = (struct dummy *) &membuff[n1 - n2];
>   n3 = sp->d3;
>
>   printf("Result = %u", n3);
>
>   exit(0);
>
> }

The indexing operator is not defined in terms of any particular integer
type.  If you write p[-2], then the value -2 is added to the pointer
value p, and the result is dereferenced.  There is no implicit
conversion of the index value (to size_t, ptrdiff_t, or anything else);
the computation just uses the value of the index.

However, in your case the index expression is ``n1 - n2''.  Both n1 and
n2 are of type unsigned int, with values 0 and 2, respectively -- which
means that the result of the subtractin is *not* -2, but UINT_MAX-2
(on your system, 4294967294U).

So your statement
    sp = (struct dummy *) &membuff[n1 - n2];
is equivalent to
    sp = (struct dummy *) &membuff[4294967294U];
and the behavior is undefined.

It's likely that &membuff[4294967294U] behaves the same way as
&membuff[-2], but the language doesn't guarantee it.  Probably the
generated code adds the value 4294967294U to the base address,
and it quietly wraps around, ignoring any overflow.  If you're
curious, take a look at the generated code (many compilers use "-S"
to generate an assembly listing).

Converting the offset value from unsigned int to int is probably
cleaner:

    int offset = n1 - n2;
    sp = (struct dummy *) &membuff[offset];

Here, &membuff[offset] is equivalent to &membuff[-2].

You seem to be retrieving 3 unsigned int values starting *before*
the beginning of the allocated block of memory.  The language
doesn't define the behavior of attempting to do that.  I'll take
your word for it that that's what you want to do and that it works.

BTW, 500 posts every day?  We *might* have that many in a month
(not including spam, but my NNTP server does a good job of filtering
that out).

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

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