Re: is this code valid?

Discussion in 'C++' started by Juha Nieminen, Jun 3, 2008.

  1. Victor Bazarov wrote:
    > Chris Thomasson wrote:
    >> The following code compiles fine with GCC, Comeau, EDG/C++ and VC++ 8/9:
    >>
    >>
    >> #include <cstdio>
    >> #include <string>
    >>
    >>
    >> int main() {
    >> {
    >> std::string names[3] = { "One", "Two", "Three" };
    >> }
    >> std::puts("\n\npress <ENTER> to exit...");
    >> std::getchar();
    >> return 0;
    >> }
    >>
    >>
    >> I think its still invalid; am I right?

    >
    > I believe you're right that you think it's still invalid (although there
    > is nobody but you that can confirm that so far, there is no way for us
    > to know what you think except when you tell us). However, I don't
    > immediately see anything invalid in the code, could you perhaps elaborate?


    There are lots of things wrong in that code. For starters, it doesn't
    check that printing to standard output succeeded.

    (Yes, that was supposed to be humoristic.)
    Juha Nieminen, Jun 3, 2008
    #1
    1. Advertising

  2. Juha Nieminen

    Guest

    On Jun 3, 4:18 pm, "Chris Thomasson" <> wrote:
    > "Victor Bazarov" <> wrote in message
    > > Chris Thomasson wrote:
    > >> : m_id(id), m_name("Default Producer"), m_Buffer(_Buffer) {
    > >> std::printf("(%p)->Producer::producer()\n", (void*)this);

    >
    > > I don't believe you need to cast 'this' here.

    >
    > Well, I thought that you could only pass a void* pointer to represent a %p
    > formatter.


    You can pass any data pointer, it's all the same. However, GCC's handy
    printf() warnings also warn when you pass a non-void* to a %p, so
    casting it does get rid of that warning. Other than squashing a
    compiler warning you don't have to do the cast.
    , Jun 4, 2008
    #2
    1. Advertising

  3. Juha Nieminen

    Guest

    On Jun 3, 8:09 pm, "Chris Thomasson" <> wrote:
    > <> wrote in message
    > > You can pass any data pointer, it's all the same.

    >
    > Even a function pointer?


    Nope (not reliably, anyways). That's why I specified *data*
    pointer. :)
    , Jun 4, 2008
    #3
  4. Juha Nieminen

    James Kanze Guest

    On Jun 3, 10:02 pm, Victor Bazarov <> wrote:
    > Chris Thomasson wrote:


    [...]
    > > : m_id(id), m_name("Default Producer"), m_Buffer(_Buffer) {
    > > std::printf("(%p)->Producer::producer()\n", (void*)this);


    > I don't believe you need to cast 'this' here.


    He's outputting to a "%p" format, which requires a void* (or
    void const*). He's passing this as a vararg. This doesn't have
    type void*. So without the cast, it's undefined behavior.

    This sort of thing is why good programmers eschew printf and
    company.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 4, 2008
    #4
  5. Juha Nieminen

    James Kanze Guest

    On Jun 4, 1:36 am, ""
    <> wrote:
    > On Jun 3, 4:18 pm, "Chris Thomasson" <> wrote:


    > > "Victor Bazarov" <> wrote in message
    > > > Chris Thomasson wrote:
    > > >> : m_id(id), m_name("Default Producer"), m_Buffer(_Buffer) {
    > > >> std::printf("(%p)->Producer::producer()\n", (void*)this);


    > > > I don't believe you need to cast 'this' here.


    > > Well, I thought that you could only pass a void* pointer to
    > > represent a %p formatter.


    > You can pass any data pointer, it's all the same.


    That is simply false. Technically, you can only pass a void*; I
    don't see anything in ISO/IEC 9899 which would even allow void
    const*. In practice, unless the implementation explicitly
    verifies, you'll also be able to pass char* and char const*,
    since they are required to have the same size and representation
    as a void*. Anything else is undefined behavior, and I've
    worked on machines where it would cause random junk to be
    output (and could even cause a core dump if there were also a %s
    or a %f elsewhere in the format string).

    > However, GCC's handy printf() warnings also warn when you pass
    > a non-void* to a %p, so casting it does get rid of that
    > warning. Other than squashing a compiler warning you don't
    > have to do the cast.


    According to the C standard, you do.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 4, 2008
    #5
  6. Juha Nieminen

    Guest

    James Kanze wrote:
    > On Jun 4, 1:36 am, ""
    > <> wrote:
    > > You can pass any data pointer, it's all the same.

    >
    > That is simply false. Technically, you can only pass a void*; I
    > don't see anything in ISO/IEC 9899 which would even allow void
    > const*. In practice, unless the implementation explicitly
    > verifies, you'll also be able to pass char* and char const*,
    > since they are required to have the same size and representation
    > as a void*. Anything else is undefined behavior, and ...


    I did not know that. Is that to say that these two statements are not
    the same:

    int i;
    int *k = &i;

    void *a = *(void **)&k; // <--- this
    void *b = (void *)k; // <--- and this

    Or does that only mean that fprintf with %p is undefined unless you
    explicitly cast pointer parameters to (void *) first? I could've sworn
    that somewhere in C++ it said that the representation for data
    pointers was always the same -- do you know where the relevant part of
    the standard is (looking in C++03, I couldn't find anything relevant).

    > ...I've
    > worked on machines where it would cause random junk to be
    > output ...


    Just out of curiosity, what machines cause things like printf("%p",
    (int *)&something); to print random junk?

    Jason
    , Jun 4, 2008
    #6
  7. Juha Nieminen

    Guest

    On Jun 4, 5:16 am, James Kanze <> wrote:
    > This sort of thing is why good programmers eschew printf and
    > company.


    Do you happen to know if C++0x is introducing a convenient ostream
    interface that makes things like:

    printf("%+9.4f %8.3f\n", value1, value2);

    Slightly easier to deal with than:

    cout << showpos << fixed << setw(9) << setprecision(4) << value1 <<
    noshowpos << setw(8) << setprecision(3) << value2 << endl;

    Do you also happen to know if C++0x is introducing an iostreams
    interface with informative error returns, e.g an equivalent of:

    string errmsg;
    if (fprintf(...) < 0)
    errmsg = strerror(errno); // <-- ?

    I find iostreams has little to no value over stdio when you are only
    dealing with built-in scalar types. Of course it's convenient to
    define new ostream << operators for complex types; but for this kind
    of stuff iostreams is incredibly cumbersome...

    Jason
    , Jun 4, 2008
    #7
  8. Juha Nieminen

    James Kanze Guest

    On Jun 4, 5:43 pm, ""
    <> wrote:
    > James Kanze wrote:
    > > On Jun 4, 1:36 am, ""
    > > <> wrote:
    > > > You can pass any data pointer, it's all the same.


    > > That is simply false. Technically, you can only pass a void*; I
    > > don't see anything in ISO/IEC 9899 which would even allow void
    > > const*. In practice, unless the implementation explicitly
    > > verifies, you'll also be able to pass char* and char const*,
    > > since they are required to have the same size and representation
    > > as a void*. Anything else is undefined behavior, and ...


    > I did not know that. Is that to say that these two statements
    > are not the same:


    > int i;
    > int *k = &i;


    > void *a = *(void **)&k; // <--- this
    > void *b = (void *)k; // <--- and this


    Certainly not. The first is undefined behavior, and will result
    in a more or less random value for a on some processors.

    > Or does that only mean that fprintf with %p is undefined
    > unless you explicitly cast pointer parameters to (void *)
    > first?


    Correct.

    > I could've sworn that somewhere in C++ it said that the
    > representation for data pointers was always the same -- do you
    > know where the relevant part of the standard is (looking in
    > C++03, I couldn't find anything relevant).


    I'm not sure I understand. You want me to point out in the
    standard where the guarantee isn't given. The real question is
    the reverse: what makes you think that an int* has the same size
    and layout as a void*.

    The fact that the standard feels it necessary to offer some
    limited guarantees should be a strong indication, however (from
    §3.9.2, paragraphs 3 and 4, from the 1998 version, since that
    and the current draft are all I have on line here):

    [...] The value representation of pointer types is
    implementation-defined. Pointers to cv-qualified and
    cv-unqualified version of layout-compatible types shall have
    the same value representation and alignment requirements.

    Objects of cv-qualified or cv-unqualified type void*
    (pointer to void) can be used to point to objects of unknown
    type. A void* shall be able to hold any object pointer. A
    cv-qualified or cv-unqualified void* shall have the same
    representation and alignment requiremns as a cv-qualified or
    cv-unqualified char*.

    In other words: const and non-const pointers to the same type
    (or a layout compatible type) must have the same representation,
    and void* and char* must have the same representation. In
    addition, the way incomplete types can be used more or less
    forces an implementation to use the same representation for all
    pointers to class types. (The only thing the representation
    could depend on is the spelling of the class name, which is, of
    course, ridiculous.)

    You might also look at the guarantees concerning casts---it's
    quite clear that casting a void* to int* and back is not
    guaranteed to result in the original pointer. That's there for
    a reason.

    > > ...I've worked on machines where it would cause random junk
    > > to be output ...


    > Just out of curiosity, what machines cause things like
    > printf("%p", (int *)&something); to print random junk?


    Word addressed machines. The machine in question had
    sizeof(int*) == 2, but sizeof(char*) == 4; the basic hardware
    pointer (16 bits) addressed words, and not bytes, and you needed
    additional bits (an additional word) to access individual bytes.

    Not so many years ago, this was the most frequent arrangment.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 4, 2008
    #8
  9. Juha Nieminen

    James Kanze Guest

    On Jun 4, 5:57 pm, ""
    <> wrote:
    > On Jun 4, 5:16 am, James Kanze <> wrote:


    > > This sort of thing is why good programmers eschew printf and
    > > company.


    > Do you happen to know if C++0x is introducing a convenient ostream
    > interface that makes things like:


    > printf("%+9.4f %8.3f\n", value1, value2);


    > Slightly easier to deal with than:


    > cout << showpos << fixed << setw(9) << setprecision(4) << value1 <<
    > noshowpos << setw(8) << setprecision(3) << value2 << endl;


    Who writes things like that? Normally you'd write something
    like:

    cout << semantic1 << value1
    << ' ' << semantic2 << value2 << endl ;

    Rather than specifying the formatting in each output statement,
    you'd define application specific formatting for the specific
    semantics of the values in your application, and use them. (For
    what it's worth, I think that setw() is the only standard
    manipulator I've ever used.)

    > Do you also happen to know if C++0x is introducing an
    > iostreams interface with informative error returns, e.g an
    > equivalent of:


    > string errmsg;
    > if (fprintf(...) < 0)
    > errmsg = strerror(errno); // <-- ?


    > I find iostreams has little to no value over stdio when you
    > are only dealing with built-in scalar types.


    If you put no value on avoiding errors and undefined behavior,
    nor on using logical mark-up, rather than low level physical
    formatting primitives, nor on being able to output to more or
    less anything, inserting filters, etc., without changing the
    code doing the outputting, then they don't add much value, no.
    I consider all three of those points important for good software
    engineering, however.

    > Of course it's convenient to define new ostream << operators
    > for complex types; but for this kind of stuff iostreams is
    > incredibly cumbersome...


    I find it less cumbersome than fprintf. And far less error
    prone.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 4, 2008
    #9
  10. Juha Nieminen

    Triple-DES Guest

    On 4 Jun, 17:57, "" <>
    wrote:
    > Do you happen to know if C++0x is introducing a convenient ostream
    > interface that makes things like:
    >
    > printf("%+9.4f %8.3f\n", value1, value2);
    >
    > Slightly easier to deal with than:
    >
    > cout << showpos << fixed << setw(9) << setprecision(4) << value1 <<
    > noshowpos << setw(8) << setprecision(3) << value2 << endl;


    Boost::format provides typesafe, "printf-like" formatting. If I'm not
    mistaken Andrei Alexandrescu also published a similar utility.

    DP
    Triple-DES, Jun 5, 2008
    #10
  11. Juha Nieminen

    Guest

    On Jun 5, 4:28 am, Triple-DES <> wrote:
    > On 4 Jun, 17:57, "" <>
    > wrote:
    >
    > > Do you happen to know if C++0x is introducing a convenient ostream
    > > interface that makes things like:

    >
    > > printf("%+9.4f %8.3f\n", value1, value2);

    >
    > > Slightly easier to deal with than:

    >
    > > cout << showpos << fixed << setw(9) << setprecision(4) << value1 <<
    > > noshowpos << setw(8) << setprecision(3) << value2 << endl;

    >
    > Boost::format provides typesafe, "printf-like" formatting. If I'm not
    > mistaken Andrei Alexandrescu also published a similar utility.


    Thanks for pointing this out; I messed around with it and have been
    using it for a couple of days now. It's really pretty cool. Maybe I'll
    start dumping the printf habit after all. Maybe.

    Jason
    , Jun 8, 2008
    #11
    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. Replies:
    2
    Views:
    430
    Adam P. Jenkins
    Jan 18, 2005
  2. Eric Biller

    Embedding VRML-Objects in valid code

    Eric Biller, Nov 13, 2003, in forum: HTML
    Replies:
    6
    Views:
    3,739
    Toby A Inkster
    Nov 14, 2003
  3. Gianni Mariani

    is this code valid ?

    Gianni Mariani, May 17, 2004, in forum: C++
    Replies:
    5
    Views:
    354
    Gianni Mariani
    May 19, 2004
  4. Replies:
    64
    Views:
    1,231
    Dave Thompson
    Dec 20, 2004
  5. Any C code are valid C++ code?

    , Dec 10, 2004, in forum: C Programming
    Replies:
    67
    Views:
    1,146
    Dave Thompson
    Dec 20, 2004
Loading...

Share This Page