printf("%p\n", (void *)0);

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Tim Rentsch

    Re: Types, Re: printf("%p \n", (void *)0);

    pete <pfiland@mindsp ring.com> writes:
    [color=blue]
    > Tim Rentsch wrote:[color=green]
    > >
    > > pete <pfiland@mindsp ring.com> writes:
    > >[color=darkred]
    > > > The only two incomplete types that I'm aware of are
    > > > void
    > > > and ones of the form
    > > > array[][/color]
    > >
    > > Also 'struct whatever' when a definition for the struct
    > > has not yet been given. (And union too of course...)[/color]
    >
    > Thank you.
    > I believe "definition " isn't the best word to use there.[/color]

    Right. The language used in the standard document is different - it
    speaks of a struct or union type having "unknown content", and the
    appearance a type declaration with stuff between the braces as
    "defining the content" of a struct or union type, and struct/union
    tags are only declared, whether or not they have their content defined
    with a '{ member-list }' clause.

    Of course, what I meant was that something like 'struct whatever' would
    declare the type, and 'struct whatever { int foo; }' would define the
    type, and probably that's what most people understood. But you're
    right that it doesn't match the language of the standard document.

    So my statement might be emended as:

    Also 'struct whatever' when the struct content has not yet been
    defined. (And union too of course...)

    Comment

    • Stephen Sprunk

      Re: printf(&quot;%p \n&quot;, (void *)0);

      "CBFalconer " <cbfalconer@yah oo.com> wrote in message
      news:423DCD17.9 AE68753@yahoo.c om...[color=blue]
      > "Trevor L. Jackson, III" wrote:[color=green]
      > > Why would you want to? Well, C is a system implementation
      > > language. And C is not the only language that can handle pointers.
      > > For instance, on a system with memory management hardware one
      > > might want to pass the address of free()'d entities to a mmgt
      > > function so that it could stop caching, buffering, synchronizing,
      > > unmap, or whatever it does to memory at the indicated address.
      > > Does a typical C implementation support that? Of course not.
      > > Should it? almost certainly not. Should it forbid it? Absolutely
      > > not.[/color][/color]

      Any added features such as those described should either be disabled prior
      to calling free() or included in the implementation of free() itself.
      [color=blue]
      > Absolutely yes. The only module that can handle your scenario
      > properly is the malloc module, which is part of the runtime system
      > for very good reasons. C knows nothing whatsoever about caching,
      > buffering, etc. This has nothing to do with the language the
      > malloc module is written in, except that we know it cannot be
      > conforming C.[/color]

      That user code (perhaps the code for the malloc module itself) calls
      non-standard functions of the OS is no reason for the implementation to
      refuse to compile that code. It may invoke UB or IDB, but it's not the
      compiler's job to tell the user he _can't_ do that, though it might be
      useful for it to warn the user that doing so relies on UB or IDB.
      [color=blue]
      > C knows nothing whatsoever about caching, buffering, etc. This has
      > nothing to do with the language the malloc module is written in,
      > except that we know it cannot be conforming C.[/color]

      Are you saying that it is impossible to implement malloc() et al in
      conforming C? Or just the extra features Trevor listed?

      S

      --
      Stephen Sprunk "Stupid people surround themselves with smart
      CCIE #3723 people. Smart people surround themselves with
      K5SSS smart people who disagree with them." --Aaron Sorkin

      Comment

      • Trevor L. Jackson, III

        Re: printf(&quot;%p \n&quot;, (void *)0);

        CBFalconer wrote:[color=blue]
        > "Trevor L. Jackson, III" wrote:
        >
        > ... snip ...
        >[color=green]
        >>Why would you want to? Well, C is a system implementation language.
        >>And C is not the only language that can handle pointers. For instance,
        >>on a system with memory management hardware one might want to pass the
        >>address of free()'d entities to a mmgt function so that it could stop
        >>caching, buffering, synchronizing, unmap, or whatever it does to memory
        >>at the indicated address. Does a typical C implementation support that?
        >>Of course not. Should it? almost certainly not. Should it forbid it?
        >>Absolutely not.[/color]
        >
        >
        > Absolutely yes. The only module that can handle your scenario
        > properly is the malloc module, which is part of the runtime system
        > for very good reasons. C knows nothing whatsoever about caching,
        > buffering, etc.[/color]

        C does not. C applications may. And the malloc module will probably be
        written, you geuessed it, C.
        [color=blue]
        > This has nothing to do with the language the
        > malloc module is written in, except that we know it cannot be
        > conforming C.[/color]

        Why not?

        Comment

        • Trevor L. Jackson, III

          Re: printf(&quot;%p \n&quot;, (void *)0);

          Keith Thompson wrote:
          [color=blue]
          > "Trevor L. Jackson, III" <tlj3@comcast.n et> writes:
          >[color=green]
          >>Keith Thompson wrote:
          >>[color=darkred]
          >>>"Trevor L. Jackson, III" <tlj3@comcast.n et> writes:
          >>>
          >>>
          >>>>Douglas A. Gwyn wrote:
          >>>>
          >>>>
          >>>>
          >>>>>"Trevor L. Jackson, III" wrote:
          >>>>>
          >>>>>
          >>>>>
          >>>>>>So realloc() is explicitly defined to not handle stale pointers?
          >>>>>
          >>>>>How would you pass the pointer value as an argument without
          >>>>>evaluati ng it?
          >>>>
          >>>>You can't directly. You can indirectly.
          >>>
          >>>How?
          >>>In particular, the following invokes undefined behavior by evaluating
          >>>the stale pointer before passing it (directly) to realloc():
          >>>#include <stdlib.h>
          >>>#include <assert.h>
          >>>int main(void)
          >>>{
          >>> int *ptr = malloc(sizeof *ptr);
          >>> assert(ptr != NULL);
          >>> free(ptr); /* * ptr is now stale */
          >>> ptr = realloc(ptr, 2 * sizeof *ptr);
          >>> return 0;
          >>>}
          >>>How would you do this indirectly? (And why would you want to?)[/color]
          >>
          >>I'm interpreting your question to be "how would you do this indirectly
          >>_to_realloc() _." You can't.[/color]
          >
          >
          > Ok. I assumed, from the context, that you were saying a stale pointer
          > can be passed to realloc() indirectly.[/color]

          Sorry if I mislead you. I'll try to be more precise in the future.
          [color=blue]
          > You meant that it can be
          > passed to some arbitrary function indirectly, which of course is true.
          > (If nothing else, you can break it down to an array of unsigned char.)[/color]

          Good point. I should have mentioned that.
          [color=blue]
          > And yes, there could be any number of reasons why you'd want to do
          > this (just to see what stale pointers look like, if nothing else).
          >[/color]

          Comment

          • James Kuyper

            Re: printf(&quot;%p \n&quot;, (void *)0);

            Stephen Sprunk wrote:[color=blue]
            > "CBFalconer " <cbfalconer@yah oo.com> wrote in message
            > news:423DCD17.9 AE68753@yahoo.c om...[/color]
            ....[color=blue][color=green]
            >>C knows nothing whatsoever about caching, buffering, etc. This has
            >>nothing to do with the language the malloc module is written in,
            >>except that we know it cannot be conforming C.[/color]
            >
            >
            > Are you saying that it is impossible to implement malloc() et al in
            > conforming C? Or just the extra features Trevor listed?[/color]

            That's what he's said, but it's wrong - conforming C code has very few
            limitations on what it can do (off hand, I can't think of any). If you
            change "conforming " to "strictly conforming" his statement becomes more
            accurate. The fundamental problem is that strictly conforming C programs
            have only one possible mechanism for obtaining a pointer to a block of
            memory that is guaranteed to have universal alignment (correct alignment
            for all possible objects). That method is to call malloc(). If written
            in strictly conforming C code, malloc() has no way to do that (a
            recursive call to malloc() is obviously not a solution to the problem),
            yet it is required by the standard to return such a pointer.

            For practical purposes, an implementation of malloc() could be written
            that allocates from a fixed static array of memory. The array would have
            a union type, where the union has members of many different types. The
            wider the variety of types in the union, the more likely it is to have
            universal alignment. In practice, if the union contains short, int,
            long, long long, float, double, long double, void*, and void(*)(void),
            it's got a pretty good chance of having universal alignment. However,
            there's no finite set of types which is guaranteed by the standard to
            give such a union universal alignment.

            Comment

            • pete

              Re: printf(&quot;%p \n&quot;, (void *)0);

              James Kuyper wrote:
              [color=blue]
              > For practical purposes, an implementation of malloc() could be written
              > that allocates from a fixed static array of memory.
              > The array would have
              > a union type, where the union has members of many different types. The
              > wider the variety of types in the union, the more likely it is to have
              > universal alignment. In practice, if the union contains short, int,
              > long, long long, float, double, long double, void*, and void(*)(void),
              > it's got a pretty good chance of having universal alignment. However,
              > there's no finite set of types which is guaranteed by the standard to
              > give such a union universal alignment.[/color]

              That wouldn't work.
              In order to access the array of unions, as an array of shorts,
              the union has to be aligned for an array of shorts,
              not merely aligned for short.

              --
              pete

              Comment

              • CBFalconer

                Re: printf(&quot;%p \n&quot;, (void *)0);

                Stephen Sprunk wrote:[color=blue]
                >[/color]
                .... snip ...[color=blue]
                >[color=green]
                >> C knows nothing whatsoever about caching, buffering, etc. This has
                >> nothing to do with the language the malloc module is written in,
                >> except that we know it cannot be conforming C.[/color]
                >
                > Are you saying that it is impossible to implement malloc() et al in
                > conforming C? Or just the extra features Trevor listed?[/color]

                Yes. Both. The fundamental bind is alignment. After that comes
                practicality. Otherwise you could declare:

                static unsigned char programPseudoHe ap[GARGANTUAN_NUMB ER];

                and dole stuff out from there. That would mean helloworld would
                require at least GARGANTUAN_NUMB ER bytes of data space. Seems like
                a waste. However the technique is usable with advance alignment
                knowledge to thrash out new versions of malloc on a particular
                system. See nmalloc.zip on my download section for an example with
                all debuggery enabled.

                --
                "I conclude that there are two ways of constructing a software
                design: One way is to make it so simple that there are obviously
                no deficiencies and the other way is to make it so complicated
                that there are no obvious deficiencies." -- C. A. R. Hoare


                Comment

                • Keith Thompson

                  Re: printf(&quot;%p \n&quot;, (void *)0);

                  pete <pfiland@mindsp ring.com> writes:
                  [...][color=blue]
                  > That wouldn't work.
                  > In order to access the array of unions, as an array of shorts,
                  > the union has to be aligned for an array of shorts,
                  > not merely aligned for short.[/color]

                  I don't believe it's possible for a short and an array of shorts to
                  have different required alignments. If short is 16 bits, a compiler
                  might choose to use, say, 32-bit alignment for arrays of shorts, but
                  it still has to be able to access an array of shorts that's 16-bit
                  aligned. For some purposes, a single short object is equivalent to an
                  array of 1 short.

                  --
                  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

                  • pete

                    Re: printf(&quot;%p \n&quot;, (void *)0);

                    Keith Thompson wrote:[color=blue]
                    >
                    > pete <pfiland@mindsp ring.com> writes:
                    > [...][color=green]
                    > > That wouldn't work.
                    > > In order to access the array of unions, as an array of shorts,
                    > > the union has to be aligned for an array of shorts,
                    > > not merely aligned for short.[/color]
                    >
                    > I don't believe it's possible for a short and an array of shorts to
                    > have different required alignments. If short is 16 bits, a compiler
                    > might choose to use, say, 32-bit alignment for arrays of shorts, but
                    > it still has to be able to access an array of shorts that's 16-bit
                    > aligned. For some purposes, a single short object is equivalent to an
                    > array of 1 short.[/color]

                    My argument comes from this

                    /* BEGIN new.c */

                    #include <stdio.h>

                    int main(void)
                    {
                    int array[2][2] = {0};
                    int *pointer = (int *)&array;

                    printf("%d\n", pointer[3]);
                    return 0;
                    }

                    /* END new.c */

                    not being OK, as has been discussed on comp.std.c before.

                    --
                    pete

                    Comment

                    • kuyper@wizard.net

                      Re: printf(&quot;%p \n&quot;, (void *)0);

                      pete wrote:[color=blue]
                      > James Kuyper wrote:
                      >[color=green]
                      > > For practical purposes, an implementation of malloc() could be[/color][/color]
                      written[color=blue][color=green]
                      > > that allocates from a fixed static array of memory.
                      > > The array would have
                      > > a union type, where the union has members of many different types.[/color][/color]
                      The[color=blue][color=green]
                      > > wider the variety of types in the union, the more likely it is to[/color][/color]
                      have[color=blue][color=green]
                      > > universal alignment. In practice, if the union contains short, int,
                      > > long, long long, float, double, long double, void*, and[/color][/color]
                      void(*)(void),[color=blue][color=green]
                      > > it's got a pretty good chance of having universal alignment.[/color][/color]
                      However,[color=blue][color=green]
                      > > there's no finite set of types which is guaranteed by the standard[/color][/color]
                      to[color=blue][color=green]
                      > > give such a union universal alignment.[/color]
                      >
                      > That wouldn't work.
                      > In order to access the array of unions, as an array of shorts,
                      > the union has to be aligned for an array of shorts,
                      > not merely aligned for short.[/color]

                      On most platforms, I would expect that the alignment requirements for
                      an array of shorts will be identical to the alignment requirements for
                      a single short int. On the platforms where that isn't true, you'd have
                      to add a member of type "array of short" to the union, which is an
                      example of why it's impossible to cover all theoretical possibilities
                      with a finite list of types.

                      Comment

                      • Wojtek Lerch

                        Re: printf(&quot;%p \n&quot;, (void *)0);

                        "Keith Thompson" <kst-u@mib.org> wrote in message
                        news:lnvf7k4xmj .fsf@nuthaus.mi b.org...[color=blue]
                        > I don't believe it's possible for a short and an array of shorts to
                        > have different required alignments. If short is 16 bits, a compiler
                        > might choose to use, say, 32-bit alignment for arrays of shorts, but
                        > it still has to be able to access an array of shorts that's 16-bit
                        > aligned. For some purposes, a single short object is equivalent to an
                        > array of 1 short.[/color]

                        But couldn't arrays of two or more shorts require 32-bit alignment?
                        Couldn't arrays of 2048 or more shorts, on the same implementation, require
                        128-bit alignment?


                        Comment

                        • Keith Thompson

                          Re: printf(&quot;%p \n&quot;, (void *)0);

                          pete <pfiland@mindsp ring.com> writes:[color=blue]
                          > Keith Thompson wrote:[color=green]
                          >> pete <pfiland@mindsp ring.com> writes:
                          >> [...][color=darkred]
                          >> > That wouldn't work.
                          >> > In order to access the array of unions, as an array of shorts,
                          >> > the union has to be aligned for an array of shorts,
                          >> > not merely aligned for short.[/color]
                          >>
                          >> I don't believe it's possible for a short and an array of shorts to
                          >> have different required alignments. If short is 16 bits, a compiler
                          >> might choose to use, say, 32-bit alignment for arrays of shorts, but
                          >> it still has to be able to access an array of shorts that's 16-bit
                          >> aligned. For some purposes, a single short object is equivalent to an
                          >> array of 1 short.[/color]
                          >
                          > My argument comes from this
                          >
                          > /* BEGIN new.c */
                          >
                          > #include <stdio.h>
                          >
                          > int main(void)
                          > {
                          > int array[2][2] = {0};
                          > int *pointer = (int *)&array;
                          >
                          > printf("%d\n", pointer[3]);
                          > return 0;
                          > }
                          >
                          > /* END new.c */
                          >
                          > not being OK, as has been discussed on comp.std.c before.[/color]

                          If that's invalid, it's not becaues of alignment, it's because the
                          array of int being indexed has only two elements. (I offer no opinion
                          on the previous argument.)

                          --
                          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

                          • Keith Thompson

                            Re: printf(&quot;%p \n&quot;, (void *)0);

                            "Wojtek Lerch" <Wojtek_L@yahoo .ca> writes:[color=blue]
                            > "Keith Thompson" <kst-u@mib.org> wrote in message
                            > news:lnvf7k4xmj .fsf@nuthaus.mi b.org...[color=green]
                            >> I don't believe it's possible for a short and an array of shorts to
                            >> have different required alignments. If short is 16 bits, a compiler
                            >> might choose to use, say, 32-bit alignment for arrays of shorts, but
                            >> it still has to be able to access an array of shorts that's 16-bit
                            >> aligned. For some purposes, a single short object is equivalent to an
                            >> array of 1 short.[/color]
                            >
                            > But couldn't arrays of two or more shorts require 32-bit alignment?
                            > Couldn't arrays of 2048 or more shorts, on the same implementation, require
                            > 128-bit alignment?[/color]

                            If you declare an array of type short[2049], you should be able to
                            access elements 1..2048 as an array of type short[2048]. (I'm too
                            tired right now either to support this with citations from the
                            standard or to provide sample code.)

                            --
                            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

                            • Wojtek Lerch

                              Re: printf(&quot;%p \n&quot;, (void *)0);

                              "Keith Thompson" <kst-u@mib.org> wrote in message
                              news:lnis3k4eoh .fsf@nuthaus.mi b.org...[color=blue]
                              > pete <pfiland@mindsp ring.com> writes:[color=green]
                              >> int array[2][2] = {0};
                              >> int *pointer = (int *)&array;[/color]
                              >
                              > If that's invalid, it's not becaues of alignment, it's because the
                              > array of int being indexed has only two elements. (I offer no opinion
                              > on the previous argument.)[/color]

                              Also because the standard never says anything about the result of the
                              conversion of a pointer to an array to a pointer to int. We all know that
                              the intention was that the result of a pointer conversions always points to
                              an object that has the same first byte (except when such an object would
                              violate alignment requirements), but I don't think you can find such a
                              general promise in the standard.


                              Comment

                              • Wojtek Lerch

                                Re: printf(&quot;%p \n&quot;, (void *)0);

                                "Keith Thompson" <kst-u@mib.org> wrote in message
                                news:lneke84eiv .fsf@nuthaus.mi b.org...[color=blue]
                                > "Wojtek Lerch" <Wojtek_L@yahoo .ca> writes:[color=green]
                                >> "Keith Thompson" <kst-u@mib.org> wrote in message
                                >> news:lnvf7k4xmj .fsf@nuthaus.mi b.org...[color=darkred]
                                >>> I don't believe it's possible for a short and an array of shorts to
                                >>> have different required alignments. If short is 16 bits, a compiler
                                >>> might choose to use, say, 32-bit alignment for arrays of shorts, but
                                >>> it still has to be able to access an array of shorts that's 16-bit
                                >>> aligned. For some purposes, a single short object is equivalent to an
                                >>> array of 1 short.[/color]
                                >>
                                >> But couldn't arrays of two or more shorts require 32-bit alignment?
                                >> Couldn't arrays of 2048 or more shorts, on the same implementation,
                                >> require
                                >> 128-bit alignment?[/color]
                                >
                                > If you declare an array of type short[2049], you should be able to
                                > access elements 1..2048 as an array of type short[2048]. (I'm too
                                > tired right now either to support this with citations from the
                                > standard or to provide sample code.)[/color]

                                You can access those elements as if they were elements of an array of 2048
                                shorts, simply by ignoring the fact that it's not undefined behaviour to
                                subtract one from &arr[1]; but I don't think you'll find a citation to
                                demonstrate that it's OK to convert &arr[1] to (short (*)[2048]).


                                Comment

                                Working...