(part 38) Han from China answers your C questions

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Borked Pseudo Mailed

    (part 38) Han from China answers your C questions

    Pointer to pointer

    James Kuyper said:
    > printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
    >
    The "%p" format specifier expects a void* argument. This is one of the
    few places where a cast is routinely needed and perfectly correct:
    >
    printf("*a=%p *p=%p %c %s\n", (void*)*a, (void*)*p, **p, *p);
    printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
    Ben Bacarisse said:
    > printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
    Technical matter: %p expects arguments of type void * and the
    conversion is not done automatically so you need to write:
    >
    printf("*a=%p *p=%p %c %s\n", (void *)*a, (void *)*p, **p, *p);
    I'm not sure James and Ben have this right, but I'd say it's more
    probable I'm wrong here. Still, we'll see. CLC psychology dictates
    that if I'm wrong, a dozen people with a grudge will be quick to
    correct me.

    6.2.5 (27) says the following:

    "A pointer to void shall have the same representation and alignment
    requirements as a pointer to a character type."

    And then a footnote for that says:

    "The same representation and alignment requirements are meant to
    imply interchangeabil ity as arguments to functions ..."

    The OP is passing a (char *) to %p. Therefore, he doesn't need to
    cast the printf() arguments to (void *).

    This is the Unix execl() case in reverse. The function execl(),
    for those terminally in ANSI/ISO C land, uses a null character
    pointer - i.e., (char *)0 or (char *)NULL - to indicate the end
    of its variable-length argument list.

    execl("/path/file", "arg", "arg", "arg", NULL);

    works if NULL is defined as ((void *) 0), whereas it's not
    guaranteed to work if NULL is defined as 0.

    Yours,
    Han from China

  • Richard Tobin

    #2
    Re: (part 38) Han from China answers your C questions

    In article <92cac0c89d7a3d dd3428a5a149099 b44@pseudo.bork ed.net>,
    Borked Pseudo Mailed <nobody@pseudo. borked.netwrote :
    >> printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
    >I'm not sure James and Ben have this right, but I'd say it's more
    >probable I'm wrong here. Still, we'll see. CLC psychology dictates
    >that if I'm wrong, a dozen people with a grudge will be quick to
    >correct me.
    Okey dokey.
    "A pointer to void shall have the same representation and alignment
    requirements as a pointer to a character type."
    The supposed problem here is that even though they have the same
    representation, they may be passed to variadic functions in a
    different way. One can imagine this really happening for, say,
    ints and doubles, but that it should happen for char * and void *
    is implausible.
    >And then a footnote for that says:
    >
    "The same representation and alignment requirements are meant to
    imply interchangeabil ity as arguments to functions ..."
    Footnotes are not normative, but this one strongly suggests that the
    committee meant it to work.

    -- Richard
    --
    Please remember to mention me / in tapes you leave behind.

    Comment

    • Ben Bacarisse

      #3
      Re: (part 38) Han from China answers your C questions

      Borked Pseudo Mailed <nobody@pseudo. borked.netwrite s:
      Pointer to pointer
      >
      James Kuyper said:
      >> printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
      >>
      >The "%p" format specifier expects a void* argument. This is one of the
      >few places where a cast is routinely needed and perfectly correct:
      >>
      >printf("*a=% p *p=%p %c %s\n", (void*)*a, (void*)*p, **p, *p);
      > printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
      >
      Ben Bacarisse said:
      >> printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
      >Technical matter: %p expects arguments of type void * and the
      >conversion is not done automatically so you need to write:
      >>
      > printf("*a=%p *p=%p %c %s\n", (void *)*a, (void *)*p, **p, *p);
      >
      I'm not sure James and Ben have this right, but I'd say it's more
      probable I'm wrong here.
      In the end, my view is that there is no way to escape the effect of
      the "shall be a pointer to void" in the description of %p. See
      section 4 (Conformance) paragraph 2 -- violating a shall (that is not
      a constraint) is undefined behaviour.
      Still, we'll see. CLC psychology dictates
      that if I'm wrong, a dozen people with a grudge will be quick to
      correct me.
      >
      6.2.5 (27) says the following:
      >
      "A pointer to void shall have the same representation and alignment
      requirements as a pointer to a character type."
      >
      And then a footnote for that says:
      >
      "The same representation and alignment requirements are meant to
      imply interchangeabil ity as arguments to functions ..."
      >
      The OP is passing a (char *) to %p. Therefore, he doesn't need to
      cast the printf() arguments to (void *).
      Despite the same representation and alignment, printf (and friends)
      may do something non-C-like and specifically permitted (by, say, the
      hardware) only for void *s since the standard assures the
      implementation that the argument will be a void * and nothing else.

      I find it hard to image that it will fail (for a char *) but I also
      find it much simpler to cast to void * as specified by the
      specification of printf. If I were forced into an alternate, more
      expensive, algorithm by a corner case in the standard I might be
      tempted to document the choice and wing it, but that is not the case
      here.

      --
      Ben.

      Comment

      • jameskuyper

        #4
        Re: (part 38) Han from China answers your C questions

        Borked Pseudo Mailed wrote:
        Pointer to pointer
        >
        James Kuyper said:
        printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
        The "%p" format specifier expects a void* argument. This is one of the
        few places where a cast is routinely needed and perfectly correct:

        printf("*a=%p *p=%p %c %s\n", (void*)*a, (void*)*p, **p, *p);
        printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
        >
        Ben Bacarisse said:
        printf("*a=%p *p=%p %c %s\n", *a, *p, **p, *p);
        Technical matter: %p expects arguments of type void * and the
        conversion is not done automatically so you need to write:

        printf("*a=%p *p=%p %c %s\n", (void *)*a, (void *)*p, **p, *p);
        >
        I'm not sure James and Ben have this right, but I'd say it's more
        probable I'm wrong here. Still, we'll see. CLC psychology dictates
        that if I'm wrong, a dozen people with a grudge will be quick to
        correct me.
        >
        6.2.5 (27) says the following:
        >
        "A pointer to void shall have the same representation and alignment
        requirements as a pointer to a character type."
        >
        And then a footnote for that says:
        >
        "The same representation and alignment requirements are meant to
        imply interchangeabil ity as arguments to functions ..."
        The tricky point is that while "it is meant to imply
        interchangeabil ty", it doesn't actually imply it. It's quite feasible
        (easy, even) to invent a function calling convention where having the
        same representation and alignment is not sufficient to ensure
        interchangeabil ity. To take the most direct approach, consider a
        function calling convention where each argument is explicitly tagged
        according to type. Less directly, consider an API that passes void*
        pointers through a different method than char* pointers.

        The key point is that while the footnote expresses the intent, the
        actual words of the standard fail to mandate that the intent be
        achieved. I'd be much happier if the standard said explicitly and
        directly, in the normative text (footnotes are not normative), that
        these type were interchangeable for the specified purposes.

        Comment

        Working...