%p and casting

Discussion in 'C Programming' started by 127.0.0.1, Sep 14, 2003.

  1. 127.0.0.1

    127.0.0.1 Guest

    Hello!

    #include <stdio.h>

    int main(void)
    {
    char *p = "hello, world";

    printf("%p\n", p);

    return 0;
    }

    Why doesn't GCC 3.2 issue a diagnostic when I compile the above code with
    '-W -Wall -ansi -pedantic -O'? How is char * different from int * or double
    *, which cause a 'warning: void format, different type arg (arg 2)'
    diagnostic?

    Many thanks
     
    127.0.0.1, Sep 14, 2003
    #1
    1. Advertising

  2. 127.0.0.1

    Simon Biber Guest

    "127.0.0.1" <> wrote:
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > char *p = "hello, world";
    >
    > printf("%p\n", p);
    >
    > return 0;
    > }
    >
    > Why doesn't GCC 3.2 issue a diagnostic when I compile the above code with
    > '-W -Wall -ansi -pedantic -O'? How is char * different from int * or double
    > *, which cause a 'warning: void format, different type arg (arg 2)'
    > diagnostic?


    There is no requirement for any compiler to produce any diagnostic for
    the given code. There is undefined behaviour, but no constraint
    violation.

    The fact that 'gcc -W -Wall -ansi -pedantic -O' does produce a diagnostic
    for some pointer types and does not for some other pointer types is
    irrelevant and off-topic on comp.lang.c.

    --
    Simon.
     
    Simon Biber, Sep 14, 2003
    #2
    1. Advertising

  3. Simon Biber wrote:
    >"127.0.0.1" <> wrote:
    >> (...)
    >> char *p = "hello, world";
    >> printf("%p\n", p);
    >> (...)
    >>
    >> Why doesn't GCC 3.2 issue a diagnostic when I compile the above code
    >> with '-W -Wall -ansi -pedantic -O'? How is char * different from int
    >> * or double *, which cause a 'warning: void format, different type
    >> arg (arg 2)' diagnostic?


    Pointers to different types can have different representations. For
    example, a pointer to an 'int' may contain the 'word number' for the
    memory location containing that int, while a pointer to a 'void' may
    contain its 'byte number'. In that case, to convert an int* to a void*,
    the representation of the int* pointer must be multiplied with the
    number of bytes in an int.

    In normal assignments and in function calls using prototypes, the
    compiler takes care of this for you. With one exception: arguments
    passed to functions with a variable number of arguments, like printf.
    In this case the prototype doesn't say which type the function expects,
    so the compiler can't convert it for you. gcc knows what the %p format
    means, though, and warns you about it.

    > The fact that 'gcc -W -Wall -ansi -pedantic -O' does produce a
    > diagnostic for some pointer types and does not for some other pointer
    > types is irrelevant and off-topic on comp.lang.c.


    Nuts. Compilers usually have reasons for what they do. In this case, its
    reason is on-topic: As you say, it's undefined behaviour.

    --
    Hallvard
     
    Hallvard B Furuseth, Sep 14, 2003
    #3
  4. 127.0.0.1 wrote:

    > Hello!
    >
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > char *p = "hello, world";
    >
    > printf("%p\n", p);
    >
    > return 0;
    > }
    >
    > Why doesn't GCC 3.2 issue a diagnostic when I compile the above code with
    > '-W -Wall -ansi -pedantic -O'? How is char * different from int * or
    > double *, which cause a 'warning: void format, different type arg (arg 2)'
    > diagnostic?


    The representations of char * and void * are so closely related that there
    is actually some dispute as to whether the behaviour of your program is
    well-defined.

    To be safe, add the cast to (void *) anyway, just as you do when you print
    any object pointer's value.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Sep 14, 2003
    #4
  5. In 'comp.lang.c', "127.0.0.1" <> wrote:

    > #include <stdio.h>
    >
    > int main(void)
    > {
    > char *p = "hello, world";
    >
    > printf("%p\n", p);
    >
    > return 0;
    > }
    >
    > Why doesn't GCC 3.2 issue a diagnostic when I compile the above code with
    > '-W -Wall -ansi -pedantic -O'? How is char * different from int * or double
    > *, which cause a 'warning: void format, different type arg (arg 2)'
    > diagnostic?


    "%p" expects a (void*). This is what gcc is trying to say to you.

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

    --
    -ed- [remove YOURBRA before answering me]
    The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    <blank line>
    FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
     
    Emmanuel Delahaye, Sep 14, 2003
    #5
  6. 127.0.0.1

    Simon Biber Guest

    "Hallvard B Furuseth" <h.b.furuseth(nospam)@usit.uio(nospam).no> wrote:
    > Simon Biber wrote:
    > > The fact that 'gcc -W -Wall -ansi -pedantic -O' does produce a
    > > diagnostic for some pointer types and does not for some other
    > > pointer types is irrelevant and off-topic on comp.lang.c.

    >
    > Nuts. Compilers usually have reasons for what they do. In this case,
    > its reason is on-topic: As you say, it's undefined behaviour.


    Yes, it's undefined behaviour for any type except a pointer to void.

    The point the OP made is that gcc does NOT warn when the argument is a
    pointer to char, but DOES warn for other pointer types, eg. (int *),
    (double *).

    The compiler probably has a reason for that, but according to the standard
    it's equally undefined behaviour for (char *), (int *) or (double *), yet
    gcc behaves differently for char* than for int* or double*.

    --
    Simon.
     
    Simon Biber, Sep 14, 2003
    #6
  7. 127.0.0.1

    Edd Dawson Guest

    "127.0.0.1" <> wrote in message news:<bk1gmi$919$>...
    > Hello!
    >
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > char *p = "hello, world";
    >
    > printf("%p\n", p);
    >
    > return 0;
    > }
    >
    > Why doesn't GCC 3.2 issue a diagnostic when I compile the above code with
    > '-W -Wall -ansi -pedantic -O'? How is char * different from int * or double
    > *, which cause a 'warning: void format, different type arg (arg 2)'
    > diagnostic?


    I think in the ANSI C standard you can set void pointers to the value
    of pointers to other types (and vice versa) without cast. So you
    shouldn't get a warning.

    Edd
     
    Edd Dawson, Sep 14, 2003
    #7
  8. "127.0.0.1" <> wrote in message news:<bk1gmi$919$>...
    > Hello!
    >
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > char *p = "hello, world";
    >
    > printf("%p\n", p);
    >
    > return 0;
    > }
    >
    > Why doesn't GCC 3.2 issue a diagnostic when I compile the above code with
    > '-W -Wall -ansi -pedantic -O'? How is char * different from int * or double
    > *, which cause a 'warning: void format, different type arg (arg 2)'
    > diagnostic?
    >
    > Many thanks


    The standard says: The corresponding argument shall be a pointer to a
    pointer to void. The input item is converted to a pointer value in an
    implementation-defined manner. If the input item is a value converted earlier
    during the same program execution, the pointer that results shall compare
    equal to that value; otherwise the behavior of the %p conversion is undefined.

    You should use printf("%p\n", (void **)p); I guess.
     
    Mantorok Redgormor, Sep 14, 2003
    #8
  9. In 'comp.lang.c', (Mantorok Redgormor) wrote:

    > The standard says: The corresponding argument shall be a pointer to a
    > pointer to void. The input item is converted to a pointer value in an
    > implementation-defined manner. If the input item is a value converted
    > earlier during the same program execution, the pointer that results
    > shall compare equal to that value; otherwise the behavior of the %p
    > conversion is undefined.
    >
    > You should use printf("%p\n", (void **)p); I guess.


    ITYM:

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

    --
    -ed- [remove YOURBRA before answering me]
    The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    <blank line>
    FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
     
    Emmanuel Delahaye, Sep 14, 2003
    #9
  10. 127.0.0.1

    Tom Zych Guest

    Mantorok Redgormor wrote:

    > The standard says: The corresponding argument shall be a pointer to a
    > pointer to void. The input item is converted to a pointer value in an

    ^^^^^^^^^^
    > implementation-defined manner. If the input item is a value converted earlier
    > during the same program execution, the pointer that results shall compare
    > equal to that value; otherwise the behavior of the %p conversion is undefined.


    > You should use printf("%p\n", (void **)p); I guess.


    I think you're looking at the spec for fscanf, not fprintf. *printf
    takes void *.

    --
    Tom Zych
    This email address will expire at some point to thwart spammers.
    Permanent address: echo '' | rot13
     
    Tom Zych, Sep 14, 2003
    #10
  11. 127.0.0.1

    Simon Biber Guest

    "Edd Dawson" <> wrote:
    > I think in the ANSI C standard you can set void pointers to the value
    > of pointers to other types (and vice versa) without cast. So you
    > shouldn't get a warning.


    You can convert between pointer to void and any other pointer to object
    type without a cast. However, that conversion is not applied for the
    variable arguments of a function such as printf. It is wrong to pass the
    wrong type to any printf. The only correct type for the "%p" specifier
    is pointer to void.

    --
    Simon.
     
    Simon Biber, Sep 14, 2003
    #11
  12. (Edd Dawson) wrote:

    >"127.0.0.1" <> wrote in message news:<bk1gmi$919$>...
    >> Hello!
    >>
    >> #include <stdio.h>
    >>
    >> int main(void)
    >> {
    >> char *p = "hello, world";
    >>
    >> printf("%p\n", p);
    >>
    >> return 0;
    >> }
    >>
    >> Why doesn't GCC 3.2 issue a diagnostic when I compile the above code with
    >> '-W -Wall -ansi -pedantic -O'? How is char * different from int * or double
    >> *, which cause a 'warning: void format, different type arg (arg 2)'
    >> diagnostic?

    >
    >I think in the ANSI C standard you can set void pointers to the value
    >of pointers to other types (and vice versa) without cast. So you
    >shouldn't get a warning.


    Disagreed: no implicit casting takes place here. One has to explicitely
    cast the pointer-to-whatever to a pointer-to-void in above example.

    Regards

    Irrwahn
    --
    do not write: void main(...)
    do not use gets()
    do not cast the return value of malloc()
    do not fflush( stdin )
    read the c.l.c-faq: http://www.eskimo.com/~scs/C-faq/top.html
     
    Irrwahn Grausewitz, Sep 14, 2003
    #12
  13. Emmanuel Delahaye <> spoke thus:

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


    So printf( "%p\n", p ) is non-standard?

    --
    Christopher Benson-Manica | Jumonji giri, for honour.
    ataru(at)cyberspace.org |
     
    Christopher Benson-Manica, Sep 14, 2003
    #13
  14. Emmanuel Delahaye, Sep 14, 2003
    #14
  15. Emmanuel Delahaye wrote:

    > In 'comp.lang.c', Christopher Benson-Manica <>
    > wrote:
    >
    >> Emmanuel Delahaye <> spoke thus:
    >>
    >>> printf("%p\n", (void *)p);

    >>
    >> So printf( "%p\n", p ) is non-standard?

    >
    > It invokes an undefined behaviour.


    Chapter and verse please, assuming that p is of type char * and that a valid
    printf prototype is in scope.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
     
    Richard Heathfield, Sep 14, 2003
    #15
  16. Richard Heathfield <> wrote:

    >Emmanuel Delahaye wrote:
    >
    >> In 'comp.lang.c', Christopher Benson-Manica <>
    >> wrote:
    >>
    >>> Emmanuel Delahaye <> spoke thus:
    >>>
    >>>> printf("%p\n", (void *)p);
    >>>
    >>> So printf( "%p\n", p ) is non-standard?

    >>
    >> It invokes an undefined behaviour.

    >
    >Chapter and verse please, assuming that p is of type char * and that a valid
    >printf prototype is in scope.


    Hm, I tend to agree with ED, but maybe I misunderstood the following
    (quoted from n843):

    7.19.6.1 The fprintf function
    [...]
    [#8] The conversion specifiers and their meanings are:
    [...]
    p The argument shall be a pointer to void. The value
    of the pointer is converted to a sequence of
    printable characters, in an implementation-defined
    manner.
    [...]
    [#9] [...] If any argument is not the correct type
    for the corresponding coversion specification, the behavior
    is undefined.

    IMHO this leads to:

    #include <stdio.h>

    int main(void)
    {
    char *p;
    printf( "%p\n", p ); /* undefined behaviour! */
    return 0;
    }

    Please correct me if I'm wrong.

    Regards

    Irrwahn
    --
    Close your eyes and press escape three times.
     
    Irrwahn Grausewitz, Sep 14, 2003
    #16
  17. Emmanuel Delahaye <> wrote:

    >In 'comp.lang.c', Christopher Benson-Manica <>
    >wrote:
    >
    >> Emmanuel Delahaye <> spoke thus:
    >>
    >>> printf("%p\n", (void *)p);

    >>
    >> So printf( "%p\n", p ) is non-standard?

    >
    >It invokes an undefined behaviour.

    .... as long as p is not of type pointer-to-void already.

    Irrwahn

    --
    Close your eyes and press escape three times.
     
    Irrwahn Grausewitz, Sep 14, 2003
    #17
  18. On Sun, 14 Sep 2003, Richard Heathfield wrote:
    >
    > Emmanuel Delahaye wrote:
    > > Christopher Benson-Manica wrote:
    > > >
    > > > So printf( "%p\n", p ) is non-standard?

    > >
    > > It invokes an undefined behaviour.

    >
    > Chapter and verse please, assuming that p is of type char * and
    > that a valid printf prototype is in scope.


    For those who don't remember the previous discussions on this
    topic, here's the relevant C&V.

    N869 6.2.5
    [#15] The three types char, signed char, and unsigned char
    are collectively called the character types. The
    implementation shall define char to have the same range,
    representation, and behavior as either signed char or
    unsigned char.

    N869 6.2.5
    [#27] A pointer to void shall have the same representation
    and alignment requirements as a pointer to a character type.


    Now, the wording of #27 is ambiguous, because of the use of the
    word "a". For example, consider the following English sentences:

    "A tin of food can feed a dog."
    "I have a dog."

    In the first case, "a" means "any" -- any tin of food can feed any
    dog at all. In the second case, "a" means "some particular one" --
    I have *one* dog. It's *not* true that for any dog at all, I have
    it!

    So we have the ambiguity. Either #27 means

    A pointer to void [is basically interchangeable with]
    a pointer to any character type at all

    or else it means

    A pointer to void [is basically interchangeable with]
    a pointer to some particular [unspecified] character type


    Obviously, the two interpretations lead to different results in
    this case; if (void *) and (char *) have the same representation,
    then printf("%p", cptr) is well-defined, and if they don't (e.g.,
    if (void *) and (unsigned char *) have the same representation,
    and char is signed), then printf("%p", p) is undefined.

    I don't know what has been done since N869 to disambiguate this
    section.

    -Arthur
     
    Arthur J. O'Dwyer, Sep 14, 2003
    #18
  19. Arthur J. O'Dwyer <> scribbled the following:
    > For those who don't remember the previous discussions on this
    > topic, here's the relevant C&V.


    > N869 6.2.5
    > [#15] The three types char, signed char, and unsigned char
    > are collectively called the character types. The
    > implementation shall define char to have the same range,
    > representation, and behavior as either signed char or
    > unsigned char.


    > N869 6.2.5
    > [#27] A pointer to void shall have the same representation
    > and alignment requirements as a pointer to a character type.



    > Now, the wording of #27 is ambiguous, because of the use of the
    > word "a". For example, consider the following English sentences:


    > "A tin of food can feed a dog."
    > "I have a dog."


    > In the first case, "a" means "any" -- any tin of food can feed any
    > dog at all. In the second case, "a" means "some particular one" --
    > I have *one* dog. It's *not* true that for any dog at all, I have
    > it!


    > So we have the ambiguity. Either #27 means


    > A pointer to void [is basically interchangeable with]
    > a pointer to any character type at all


    > or else it means


    > A pointer to void [is basically interchangeable with]
    > a pointer to some particular [unspecified] character type



    > Obviously, the two interpretations lead to different results in
    > this case; if (void *) and (char *) have the same representation,
    > then printf("%p", cptr) is well-defined, and if they don't (e.g.,
    > if (void *) and (unsigned char *) have the same representation,
    > and char is signed), then printf("%p", p) is undefined.


    > I don't know what has been done since N869 to disambiguate this
    > section.


    This is something which relates to an ambiguity often found in
    dictionaries.
    Consider this kind of entry:

    zyzzyva
    n. A small, brownish weevil that feeds on crops.

    Does this mean that any small, brownish weevil that feeds on crops is
    a zyzzyva? It most likely does NOT, but there's no way to tell without
    having knowledge outside of the dictionary.

    --
    /-- Joona Palaste () ---------------------------\
    | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
    | http://www.helsinki.fi/~palaste W++ B OP+ |
    \----------------------------------------- Finland rules! ------------/
    "I wish someone we knew would die so we could leave them flowers."
    - A 6-year-old girl, upon seeing flowers in a cemetery
     
    Joona I Palaste, Sep 14, 2003
    #19
  20. 127.0.0.1

    Ben Pfaff Guest

    Richard Heathfield <> writes:

    > The representations of char * and void * are so closely related [...]


    In fact, they are so closely related that they are required to be
    the same:

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

    (C99 6.2.5#26)
    --
    int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
    \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
    );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
    );}return 0;}
     
    Ben Pfaff, Sep 14, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Remco
    Replies:
    1
    Views:
    356
    Alvin Bruney [MVP]
    Apr 11, 2004
  2. jeffc
    Replies:
    4
    Views:
    2,749
    jeffc
    Dec 9, 2004
  3. kevin
    Replies:
    11
    Views:
    5,811
    Andrew McDonagh
    Jan 8, 2005
  4. Wally Barnes
    Replies:
    3
    Views:
    530
    Wally Barnes
    Nov 20, 2008
  5. Sosuke

    Up casting and down casting

    Sosuke, Dec 20, 2009, in forum: C++
    Replies:
    2
    Views:
    568
    James Kanze
    Dec 20, 2009
Loading...

Share This Page