Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Re: is this code valid?

Reply
Thread Tools

Re: is this code valid?

 
 
Juha Nieminen
Guest
Posts: n/a
 
      06-03-2008
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:uts("\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.)
 
Reply With Quote
 
 
 
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      06-03-2008
On Jun 3, 4:18 pm, "Chris Thomasson" <(E-Mail Removed)> wrote:
> "Victor Bazarov" <(E-Mail Removed)> wrote in message
> > Chris Thomasson wrote:
> >> : m_id(id), m_name("Default Producer"), m_Buffer(_Buffer) {
> >> std:rintf("(%p)->Producer:roducer()\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.
 
Reply With Quote
 
 
 
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      06-04-2008
On Jun 3, 8:09 pm, "Chris Thomasson" <(E-Mail Removed)> wrote:
> <(E-Mail Removed)> 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.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-04-2008
On Jun 3, 10:02 pm, Victor Bazarov <(E-Mail Removed)> wrote:
> Chris Thomasson wrote:


[...]
> > : m_id(id), m_name("Default Producer"), m_Buffer(_Buffer) {
> > std:rintf("(%p)->Producer:roducer()\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:(E-Mail Removed)
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
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-04-2008
On Jun 4, 1:36 am, "(E-Mail Removed)"
<(E-Mail Removed)> wrote:
> On Jun 3, 4:18 pm, "Chris Thomasson" <(E-Mail Removed)> wrote:


> > "Victor Bazarov" <(E-Mail Removed)> wrote in message
> > > Chris Thomasson wrote:
> > >> : m_id(id), m_name("Default Producer"), m_Buffer(_Buffer) {
> > >> std:rintf("(%p)->Producer:roducer()\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:(E-Mail Removed)
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
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      06-04-2008
James Kanze wrote:
> On Jun 4, 1:36 am, "(E-Mail Removed)"
> <(E-Mail Removed)> 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
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      06-04-2008
On Jun 4, 5:16 am, James Kanze <(E-Mail Removed)> 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( << 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
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-04-2008
On Jun 4, 5:43 pm, "(E-Mail Removed)"
<(E-Mail Removed)> wrote:
> James Kanze wrote:
> > On Jun 4, 1:36 am, "(E-Mail Removed)"
> > <(E-Mail Removed)> 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:(E-Mail Removed)
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
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-04-2008
On Jun 4, 5:57 pm, "(E-Mail Removed)"
<(E-Mail Removed)> wrote:
> On Jun 4, 5:16 am, James Kanze <(E-Mail Removed)> 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( << 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:(E-Mail Removed)
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
 
Reply With Quote
 
Triple-DES
Guest
Posts: n/a
 
      06-05-2008
On 4 Jun, 17:57, "(E-Mail Removed)" <(E-Mail Removed)>
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( << setprecision(3) << value2 << endl;


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

DP
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
what is the difference between code inside a <script> tag and code in the code-behind file? keithb ASP .Net 1 03-29-2006 01:00 AM
Fire Code behind code AND Javascript code associated to a Button Click Event =?Utf-8?B?Q2FybG8gTWFyY2hlc29uaQ==?= ASP .Net 4 02-11-2004 07:31 AM
Re: Code Behind vs. no code behind: error Ben Miller [msft] ASP .Net 1 06-28-2003 01:46 AM
Re: C# Equivalent of VB.Net Code -- One line of code, simple Ian ASP .Net 0 06-25-2003 01:14 PM
Re: C# Equivalent of VB.Net Code -- One line of code, simple Ron ASP .Net 1 06-24-2003 07:18 PM



Advertisments