Incrementing a void pointer. Legal C99?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Richard Bos

    #16
    Re: Incrementing a void pointer. Legal C99?

    Keith Thompson <kst-u@mib.org> wrote:
    [color=blue]
    > Ben Pfaff <blp@cs.stanfor d.edu> writes:[color=green]
    > > "Bill Pursell" <bill.pursell@g mail.com> writes:
    > >[color=darkred]
    > >> if ( ( ret = malloc(size)) == NULL)
    > >> perror("malloc" ), exit(-1);[/color]
    > >
    > > If you ever pass size == 0, some implementations will return NULL
    > > from malloc() and your xmalloc() implementation will abort().[/color]
    >
    > Which raises an interesting but trivial point.
    >
    > malloc() returns NULL if it's unable to allocate the requested memory.
    > malloc(0), even if it succeeds, can return either NULL or a valid
    > pointer.[/color]

    Ah. This is a philosophical point. _Is_ trying to allocate 0 bytes and
    getting nothing as a result truly a success? Contrariwise, is it truly a
    failure? Since, IMO, it is only marginally either, allowing malloc(0) to
    return either a null pointer or a pointer to non-usable memory is
    philosophically the right answer.
    It may be technically awkward in some cases, but then, any program
    should be prepared to get a null pointer from malloc() for any size, at
    any time; and also prepared for a malloc() succeeding after a previous
    one failed - for example, when another program has just terminated and
    freed a lot of memory.
    [color=blue]
    > (I'm using NULL as a verbal shorthand for a null pointer value;
    > obviously a function can't return a macro.)[/color]

    Tsk...

    Richard

    Comment

    • Dave Thompson

      #17
      Re: Incrementing a void pointer. Legal C99?

      On 4 May 2006 20:40:39 -0700, "Bill Pursell" <bill.pursell@g mail.com>
      wrote:
      [color=blue]
      >
      > Dave Thompson wrote:[color=green]
      > > On 23 Apr 2006 05:29:33 -0700, "Bill Pursell" <bill.pursell@g mail.com>
      > > wrote:[/color][/color]
      <snip>[color=blue][color=green][color=darkred]
      > > > void **ret; /* declared as void ** to allow "ret[idx]". Is this
      > > > safe?*/[/color]
      > >
      > > Not really. For your current structure you want to treat the bottom
      > > level pointers as void* = pointer to any data, but the second level as
      > > void** = pointer to pointer (to void), and the third as void*** etc.
      > > There are platforms where pointer-to-void (or character) is different
      > > from and cannot safely be treated as pointer-to-pointer. And it is
      > > allowed for pointers to any incompatible types to be different,
      > > including pointer to pointer (to void) versus pointer to pointer (to
      > > pointer to void) etc., although I don't know of any actual case.[/color]
      >
      > Thats strikes me as very counter-intuitive. If a void * can refer to
      > any kind of pointer, then it should be able to refer to an int *, or a
      > void **, or a void ***.
      >[/color]
      A void* can address any memory, but it can't be used to access it at
      all; a 'typed' pointer must be used for that. void** accesses the
      memory assuming it contains (or will do) a void*. See below.

      <big snip>[color=blue][color=green]
      > > Off by one. Your design creates pointers 'all the way down', i.e. you
      > > have 4 levels of pointers, with the lowest ones each pointing to a
      > > single element, which you apparently want to be int in this case.
      > > Assuming you solve only the leaf/higher problem above:
      > > * (int*) ((void****)foo) [i] [j] [k] [l]
      > > (Or declare foo as void**** in the first place to avoid the cast.)
      > >
      > > If not, if you left all the pointers as void*, what you actually have
      > > to do is (if I've counted right, not tested):
      > > *(int*)( (void**)( (void**)( (void**)foo)[i] )[j] )[k] )[l] )
      > > which I would certainly hide under a macro or several.[/color]
      >
      > I think this demonstrates a point that is throwing me a little.
      > It strikes me that the compiler should treat
      > ((void ****)foo)[i][j] and (void **)((void **)foo[i])[j]
      > exactly the same way. The first says
      > "foo is a pointer to a pointer to a pointer to a pointer",
      > therefore foo[i] is a pointer to a pointer to a pointer,
      > and foo[j] is a pointer to a pointer, which
      > is just made explicit by the second. I don't see how
      > the explicit double cast gives any more information to
      > the compiler.
      >[/color]
      But they are different types of pointers. void*** is a pointer to
      (something which is) a pointer to a pointer to void. The nested casts
      describe the data structure you actually created, where the root
      points to memory which actually contains a void* which points to
      memory which contains a void* which points to data, but the root does
      not point to something actually _is_ a void**.

      A void *, or [signed/unsigned] char *, must be able to point to any
      valid memory object in C, that is, any byte. But other (data) pointer
      types need only to be able to point at valid objects of their type.
      Thus an int* only needs to be able to point to an int, a struct foo*
      only needs to be able to point to a struct foo, and a void** only
      needs to be able to point to a void*. On some platforms -- including
      one I use -- these other data types are addressed as words, not as
      bytes, and thus pointers of these types have different representations
      than void*. In fact the Standard even allows them to have different
      _sizes_, and some systems have done so, although not mine.

      Thus (int*) ( (void**)foo[i] ) [j] says fetch the i'th rank2 pointer,
      which is a pointer to void (= to byte), _convert_ it to a pointer to
      void* (= a certain kind of word), use it fetch the j'th rank1 pointer,
      which is a byte pointer, convert it to pointer to int (another type of
      word), and use it to fetch the targetted int.

      On most platforms today all pointers -- at least all data pointers --
      are just byte addresses, so you can get away with cheating.
      As I think I noted some ways back. But you asked about doing it right.
      [color=blue][color=green]
      > > Alternatively you could change the recursion to terminate at rank 1
      > > and allocate a leaf 'row' of origdims[num-1] * size and:
      > > ( (int*) ((void***)foo) [i] [j] [k] ) [l]
      > > (or other adjustments as above).
      > >
      > > Or you might consider an entirely different design where you just
      > > malloc prod(alldims)*s ize and do your own subscripting as
      > > ((int*)foo) [ i1*n2*n3*n4 + i2*n3*n4 + i3*n4 + i4][/color]
      >
      > The reason I'm avoiding this is performance. I seem to be
      > able to dereference the array much faster than doing the
      > arithmetic. Of course, I could probably build the array using[/color]

      That's interesting. Historically (like in the 70s and 80s) this was
      widely the case, but on today's mainstream CPUs ALU operations are
      almost always _much_ faster than any real memory access, and generally
      at least as fast as even cached ones. Are you using small embedded
      systems, or some specialized environment like avionics or space?

      Do you need completely random access, or can you do (or encourage your
      compiler to) partial precomputation aka strength reduction?
      [color=blue]
      > the arithmetic, but I all the points you made on dereferencing the
      > pointers will remain. In practice, my upper bound on the
      > rank is a compile-time limit of 8, with realistic values never
      > exceeding 4, so I could easily incorporate explicit casts
      > on each level.
      >[/color]
      Or, for 4 and probably even rather more than 8, you could do as I also
      suggested and just write separate routines for each rank, where each
      higher one calls the next lower one. That way you can use the
      'natural' types for C, have less cluttered code, and be sure it works.

      And it even gives you a little bit of error checking: you can't
      accidentally allocate a 4D and then subscript it as 3D. Even
      (especially) after years of changes/maintenance.

      - David.Thompson1 at worldnet.att.ne t

      Comment

      • Barry Schwarz

        #18
        Re: Incrementing a void pointer. Legal C99?

        On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
        <david.thompson 1@worldnet.att. net> wrote:

        [color=blue]
        >A void* can address any memory, but it can't be used to access it at
        >all;[/color]

        A void* cannot be dereferenced to access memory; actually cannot be
        dereferenced at all. But several functions accept a void* to access
        memory, such as memcmp, qsort, etc.


        Remove del for email

        Comment

        • Harald van Dijk

          #19
          Re: Incrementing a void pointer. Legal C99?

          Barry Schwarz wrote:[color=blue]
          > On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
          > <david.thompson 1@worldnet.att. net> wrote:
          >
          >[color=green]
          > >A void* can address any memory, but it can't be used to access it at
          > >all;[/color]
          >
          > A void* cannot be dereferenced to access memory; actually cannot be
          > dereferenced at all.[/color]

          My compilers accept

          int main(void) {
          void *p = &p;
          *p;
          return 0;
          }

          gcc with -ansi -pedantic-errors gives only a warning, tcc with -Xs
          ("strict ANSI with many extra checks") gives no complaints at all. I
          don't see anything in n1124 forbidding this either. Did I miss
          something?

          Comment

          • pete

            #20
            Re: Incrementing a void pointer. Legal C99?

            =?utf-8?B?SGFyYWxkIHZ hbiBExLNr?= wrote:[color=blue]
            >
            > Barry Schwarz wrote:[color=green]
            > > On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
            > > <david.thompson 1@worldnet.att. net> wrote:
            > >
            > >[color=darkred]
            > > >A void* can address any memory, but it can't be used to access it at
            > > >all;[/color]
            > >
            > > A void* cannot be dereferenced to access memory; actually cannot be
            > > dereferenced at all.[/color]
            >
            > My compilers accept
            >
            > int main(void) {
            > void *p = &p;
            > *p;
            > return 0;
            > }
            >
            > gcc with -ansi -pedantic-errors gives only a warning, tcc with -Xs
            > ("strict ANSI with many extra checks") gives no complaints at all. I
            > don't see anything in n1124 forbidding this either. Did I miss
            > something?[/color]

            Is (*p) equal to (p[0]) ?

            --
            pete

            Comment

            • pete

              #21
              Re: Incrementing a void pointer. Legal C99?

              pete wrote:[color=blue]
              >
              > =?utf-8?B?SGFyYWxkIHZ hbiBExLNr?= wrote:[color=green]
              > >
              > > Barry Schwarz wrote:[color=darkred]
              > > > On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
              > > > <david.thompson 1@worldnet.att. net> wrote:
              > > >
              > > >
              > > > >A void* can address any memory, but it can't be used to access it at
              > > > >all;
              > > >
              > > > A void* cannot be dereferenced to access memory; actually cannot be
              > > > dereferenced at all.[/color]
              > >
              > > My compilers accept
              > >
              > > int main(void) {
              > > void *p = &p;
              > > *p;
              > > return 0;
              > > }
              > >
              > > gcc with -ansi -pedantic-errors gives only a warning,[/color][/color]

              What's the warning?
              [color=blue][color=green]
              > > tcc with -Xs
              > > ("strict ANSI with many extra checks") gives no complaints at all. I
              > > don't see anything in n1124 forbidding this either. Did I miss
              > > something?[/color]
              >
              > Is (*p) equal to (p[0]) ?[/color]

              (*puts) isn't equal to (puts[0]),
              so the point I was trying to get at, may be irrelevant.

              --
              pete

              Comment

              • Harald van Dijk

                #22
                Re: Incrementing a void pointer. Legal C99?

                pete wrote:[color=blue]
                > pete wrote:[color=green]
                > >
                > > =?utf-8?B?SGFyYWxkIHZ hbiBExLNr?= wrote:[color=darkred]
                > > >
                > > > Barry Schwarz wrote:
                > > > > On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
                > > > > <david.thompson 1@worldnet.att. net> wrote:
                > > > >
                > > > >
                > > > > >A void* can address any memory, but it can't be used to access it at
                > > > > >all;
                > > > >
                > > > > A void* cannot be dereferenced to access memory; actually cannot be
                > > > > dereferenced at all.
                > > >
                > > > My compilers accept
                > > >
                > > > int main(void) {
                > > > void *p = &p;
                > > > *p;
                > > > return 0;
                > > > }
                > > >
                > > > gcc with -ansi -pedantic-errors gives only a warning,[/color][/color]
                >
                > What's the warning?[/color]

                Simply "warning: dereferencing ‘void *’ pointer".
                [color=blue][color=green][color=darkred]
                > > > tcc with -Xs
                > > > ("strict ANSI with many extra checks") gives no complaints at all. I
                > > > don't see anything in n1124 forbidding this either. Did I miss
                > > > something?[/color]
                > >
                > > Is (*p) equal to (p[0]) ?[/color]
                >
                > (*puts) isn't equal to (puts[0]),
                > so the point I was trying to get at, may be irrelevant.[/color]

                Not even just with function pointers, but

                extern char p[];
                int main(void) {
                *&p; /* no error */
                (&p)[0]; /* gcc: error: invalid use of array with unspecified
                bounds */
                return 0;
                }

                And tcc's error message is more verbose, but essentially the same.

                Comment

                • S.Tobias

                  #23
                  Re: Incrementing a void pointer. Legal C99?

                  pete <pfiland@mindsp ring.com> wrote:[color=blue]
                  > =?utf-8?B?SGFyYWxkIHZ hbiBExLNr?= wrote:[color=green]
                  >>
                  >> Barry Schwarz wrote:[color=darkred]
                  >> > On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
                  >> > <david.thompson 1@worldnet.att. net> wrote:
                  >> >
                  >> >
                  >> > >A void* can address any memory, but it can't be used to access it at
                  >> > >all;
                  >> >
                  >> > A void* cannot be dereferenced to access memory; actually cannot be
                  >> > dereferenced at all.[/color][/color][/color]

                  6.5.3.2 doesn't constrain us from dereferencing void pointers.
                  In fact, nothing does.
                  [color=blue][color=green]
                  >>
                  >> My compilers accept
                  >>
                  >> int main(void) {
                  >> void *p = &p;
                  >> *p;
                  >> return 0;
                  >> }
                  >>
                  >> gcc with -ansi -pedantic-errors gives only a warning, tcc with -Xs
                  >> ("strict ANSI with many extra checks") gives no complaints at all. I
                  >> don't see anything in n1124 forbidding this either. Did I miss
                  >> something?[/color][/color]

                  Everything is all right.
                  [color=blue]
                  >
                  > Is (*p) equal to (p[0]) ?
                  >[/color]
                  No.

                  --
                  Stan Tobias
                  mailx `echo siXtY@FamOuS.Be dBuG.pAlS.INVALID | sed s/[[:upper:]]//g`

                  Comment

                  • Richard Heathfield

                    #24
                    Re: Incrementing a void pointer. Legal C99?

                    Harald van D?k said:
                    [color=blue]
                    > Barry Schwarz wrote:[color=green]
                    >> On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
                    >> <david.thompson 1@worldnet.att. net> wrote:
                    >>
                    >>[color=darkred]
                    >> >A void* can address any memory, but it can't be used to access it at
                    >> >all;[/color]
                    >>
                    >> A void* cannot be dereferenced to access memory; actually cannot be
                    >> dereferenced at all.[/color]
                    >
                    > My compilers accept
                    >
                    > int main(void) {
                    > void *p = &p;
                    > *p;
                    > return 0;
                    > }
                    >
                    > gcc with -ansi -pedantic-errors gives only a warning,[/color]

                    Only a warning.

                    "I'm going into the cave."
                    "I think I'd better warn you there's a mad bear in there."
                    "Oh. Well, it's only a warning. Here I gAAAAAARRRRGGGH HH!"

                    I prefer to call them "diagnostic messages". It conveys a less casual
                    approach to the often ghastly problems to which your compiler is trying to
                    draw your attention.
                    [color=blue]
                    > tcc with -Xs
                    > ("strict ANSI with many extra checks") gives no complaints at all. I
                    > don't see anything in n1124 forbidding this either. Did I miss
                    > something?[/color]

                    Well, remember that void expressions are evaluated for their side effects.
                    Now try /using/ the value of the expression, and see how far you get.

                    --
                    Richard Heathfield
                    "Usenet is a strange place" - dmr 29/7/1999

                    email: rjh at above domain (but drop the www, obviously)

                    Comment

                    • Harald van Dijk

                      #25
                      Re: Incrementing a void pointer. Legal C99?

                      Richard Heathfield wrote:[color=blue]
                      > Harald van D?k said:
                      >[color=green]
                      > > Barry Schwarz wrote:[color=darkred]
                      > >> On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
                      > >> <david.thompson 1@worldnet.att. net> wrote:
                      > >>
                      > >>
                      > >> >A void* can address any memory, but it can't be used to access it at
                      > >> >all;
                      > >>
                      > >> A void* cannot be dereferenced to access memory; actually cannot be
                      > >> dereferenced at all.[/color]
                      > >
                      > > My compilers accept
                      > >
                      > > int main(void) {
                      > > void *p = &p;
                      > > *p;
                      > > return 0;
                      > > }
                      > >
                      > > gcc with -ansi -pedantic-errors gives only a warning,[/color]
                      >
                      > Only a warning.
                      >
                      > "I'm going into the cave."
                      > "I think I'd better warn you there's a mad bear in there."
                      > "Oh. Well, it's only a warning. Here I gAAAAAARRRRGGGH HH!"
                      >
                      > I prefer to call them "diagnostic messages". It conveys a less casual
                      > approach to the often ghastly problems to which your compiler is trying to
                      > draw your attention.[/color]

                      The warning here means gcc does not believe it violates any
                      constraints, but does believe it may be an accident. It is not an
                      accident. I do not call it a "diagnostic message" because error
                      messages are that too, and I wanted to make it clear that gcc
                      successfully compiled the program.
                      [color=blue][color=green]
                      > > tcc with -Xs
                      > > ("strict ANSI with many extra checks") gives no complaints at all. I
                      > > don't see anything in n1124 forbidding this either. Did I miss
                      > > something?[/color]
                      >
                      > Well, remember that void expressions are evaluated for their side effects.
                      > Now try /using/ the value of the expression, and see how far you get.[/color]

                      Does an expression of type void even have a value? Anyway, I know there
                      is not a whole lot you can do with it, and there is no reason to do
                      this in C other than "because I can". But when it is claimed I can't,
                      that's reason enough for me.

                      Comment

                      • pete

                        #26
                        Re: Incrementing a void pointer. Legal C99?

                        =?utf-8?B?SGFyYWxkIHZ hbiBExLNr?= wrote:
                        [color=blue]
                        > Does an expression of type void even have a value?[/color]

                        No.
                        [color=blue]
                        > Anyway, I know there
                        > is not a whole lot you can do with it, and there is no reason to do
                        > this in C other than "because I can". But when it is claimed I can't,
                        > that's reason enough for me.[/color]

                        I understand.

                        --
                        pete

                        Comment

                        • Keith Thompson

                          #27
                          Re: Incrementing a void pointer. Legal C99?

                          "Harald van Dijk" <truedfx@gmail. com> writes:[color=blue]
                          > Richard Heathfield wrote:[color=green]
                          >> Harald van D?k said:[color=darkred]
                          >> > Barry Schwarz wrote:
                          >> >> On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
                          >> >> <david.thompson 1@worldnet.att. net> wrote:
                          >> >> >A void* can address any memory, but it can't be used to access it at
                          >> >> >all;
                          >> >>
                          >> >> A void* cannot be dereferenced to access memory; actually cannot be
                          >> >> dereferenced at all.
                          >> >
                          >> > My compilers accept
                          >> >
                          >> > int main(void) {
                          >> > void *p = &p;
                          >> > *p;
                          >> > return 0;
                          >> > }
                          >> >
                          >> > gcc with -ansi -pedantic-errors gives only a warning,[/color]
                          >>
                          >> Only a warning.
                          >>
                          >> "I'm going into the cave."
                          >> "I think I'd better warn you there's a mad bear in there."
                          >> "Oh. Well, it's only a warning. Here I gAAAAAARRRRGGGH HH!"
                          >>
                          >> I prefer to call them "diagnostic messages". It conveys a less casual
                          >> approach to the often ghastly problems to which your compiler is trying to
                          >> draw your attention.[/color]
                          >
                          > The warning here means gcc does not believe it violates any
                          > constraints, but does believe it may be an accident. It is not an
                          > accident. I do not call it a "diagnostic message" because error
                          > messages are that too, and I wanted to make it clear that gcc
                          > successfully compiled the program.[/color]
                          [...]

                          The standard only requires a compiler to produce a diagnostic message
                          when it encounters a syntax error or constraint violation. It doesn't
                          require a distinction between warnings and error messages, and it
                          doesn't require *any* program to be rejected (unless it contains a
                          "#error" directive).

                          So any compiler is allowed to respond to a constraint violation by
                          printing a warning message and successfully translating the file, <OT>
                          and gcc does so in some cases</OT>.

                          --
                          Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                          San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                          We must do something. This is something. Therefore, we must do this.

                          Comment

                          • Harald van Dijk

                            #28
                            Re: Incrementing a void pointer. Legal C99?

                            Keith Thompson wrote:[color=blue]
                            > "Harald van Dijk" <truedfx@gmail. com> writes:[color=green]
                            > > Richard Heathfield wrote:[color=darkred]
                            > >> Harald van D?k said:
                            > >> > Barry Schwarz wrote:
                            > >> >> On Sun, 14 May 2006 20:32:29 GMT, Dave Thompson
                            > >> >> <david.thompson 1@worldnet.att. net> wrote:
                            > >> >> >A void* can address any memory, but it can't be used to access it at
                            > >> >> >all;
                            > >> >>
                            > >> >> A void* cannot be dereferenced to access memory; actually cannot be
                            > >> >> dereferenced at all.
                            > >> >
                            > >> > My compilers accept
                            > >> >
                            > >> > int main(void) {
                            > >> > void *p = &p;
                            > >> > *p;
                            > >> > return 0;
                            > >> > }
                            > >> >
                            > >> > gcc with -ansi -pedantic-errors gives only a warning,
                            > >>
                            > >> Only a warning.
                            > >>
                            > >> "I'm going into the cave."
                            > >> "I think I'd better warn you there's a mad bear in there."
                            > >> "Oh. Well, it's only a warning. Here I gAAAAAARRRRGGGH HH!"
                            > >>
                            > >> I prefer to call them "diagnostic messages". It conveys a less casual
                            > >> approach to the often ghastly problems to which your compiler is trying to
                            > >> draw your attention.[/color]
                            > >
                            > > The warning here means gcc does not believe it violates any
                            > > constraints, but does believe it may be an accident. It is not an
                            > > accident. I do not call it a "diagnostic message" because error
                            > > messages are that too, and I wanted to make it clear that gcc
                            > > successfully compiled the program.[/color]
                            > [...]
                            >
                            > The standard only requires a compiler to produce a diagnostic message
                            > when it encounters a syntax error or constraint violation. It doesn't
                            > require a distinction between warnings and error messages, and it
                            > doesn't require *any* program to be rejected (unless it contains a
                            > "#error" directive).
                            >
                            > So any compiler is allowed to respond to a constraint violation by
                            > printing a warning message and successfully translating the file, <OT>
                            > and gcc does so in some cases</OT>.[/color]

                            I am aware that in the general case, there is no such guarantee, but I
                            mentioned I used the -pedantic-errors option, which with GCC makes
                            *all* required diagnostics hard errors. Sorry for not having posted
                            what it meant the first time.

                            Comment

                            Working...