473,322 Members | 1,421 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

is this code valid?

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 <ENTERto exit...");
std::getchar();
return 0;
}
I think its still invalid; am I right?
--
Chris M. Thomasson
http://appcore.home.comcast.net
Jun 27 '08 #1
25 1567
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 <ENTERto 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?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #2
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 <ENTERto 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.)
Jun 27 '08 #3
"Juha Nieminen" <no****@thanks.invalidwrote in message
news:yW***************@read4.inet.fi...
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 <ENTERto 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.)
lol!

:^D
Okay... Here is what I want to be able to do; the following should compile
and run fine:
__________________________________________________ _____________________
/* Active Object
__________________________________________________ ____________*/
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join
struct active {
T object;

struct guard {
T& object;

guard(T& _object) : object(_object) {
(object.*T_fp_start)();
}

~guard() {
(object.*T_fp_join)();
}
};

active() {
(object.*T_fp_start)();
}

template<typename T_p1>
active(T_p1& p1) : object(p1) {
(object.*T_fp_start)();
}

template<typename T_p1>
active(T_p1 const& p1) : object(p1) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2>
active(T_p1& p1, T_p2& p2) : object(p1, p2) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2>
active(T_p1 const& p1, T_p2& p2) : object(p1, p2) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2>
active(T_p1& p1, T_p2 const& p2) : object(p1, p2) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2>
active(T_p1 const& p1, T_p2 const& p2) : object(p1, p2) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2, typename T_p3>
active(T_p1 const& p1, T_p2& p2, T_p3& p3)
: object(p1, p2, p3) {
(object.*T_fp_start)();
}

// [and on and on for more and more parameters...]

~active() {
(object.*T_fp_join)();
}
};


/* Sample usage
__________________________________________________ ____________*/
#include <cstdio>
#include <cstddef>
#include <string>

struct Buffer {
Buffer() {
std::printf("(%p)->Buffer::Buffer()\n", (void*)this);
}

~Buffer() {
std::printf("(%p)->Buffer::~Buffer()\n", (void*)this);
}
};
struct Producer {
int const m_id;
std::string const m_name;
Buffer& m_Buffer;

Producer(int const id, Buffer& _Buffer)
: m_id(id), m_name("Default Producer"), m_Buffer(_Buffer) {
std::printf("(%p)->Producer::Producer()\n", (void*)this);
}

Producer(int const id, char const* name, Buffer& _Buffer)
: m_id(id), m_name(name), m_Buffer(_Buffer) {
std::printf("(%p)->Producer::Producer()\n", (void*)this);
}

~Producer() {
std::printf("(%p)->Producer::~Producer()\n", (void*)this);
}

void start() {
std::printf("(%p)-void Producer<'%s'>::start() - Buffer(%p)\n",
(void*)this, m_name.c_str(), (void*)&m_Buffer);
}

void join() {
std::printf("(%p)-void Producer::join() - Buffer(%p)\n",
(void*)this, (void*)&m_Buffer);
}
};
struct Consumer {
int const m_id;
std::string const m_name;
Buffer& m_Buffer;

Consumer(int const id, Buffer& _Buffer)
: m_id(id), m_name("Default Consumer"), m_Buffer(_Buffer) {
std::printf("(%p)->Consumer::Consumer()\n", (void*)this);
}

Consumer(int const id, char const* name, Buffer& _Buffer)
: m_id(id), m_name(name), m_Buffer(_Buffer) {
std::printf("(%p)->Consumer::Consumer()\n", (void*)this);
}

~Consumer() {
std::printf("(%p)->Consumer::~Consumer()\n", (void*)this);
}

void start() {
std::printf("(%p)-void Consumer<'%s'>::start() - Buffer(%p)\n",
(void*)this, m_name.c_str(), (void*)&m_Buffer);
}

void join() {
std::printf("(%p)-void Consumer::join() - Buffer(%p)\n",
(void*)this, (void*)&m_Buffer);
}
};
#define ARRAY_DEPTH(mp_this) ( \
sizeof((mp_this)) / sizeof((mp_this)[0]) \
)
int main() {
{
Buffer b;

active<Producerp[] = {
active<Producer>(123, b),
active<Producer>(456, "Custom Producer", b),
active<Producer>(789, b),
active<Producer>(234, "I am a Producer!", b),
active<Producer>(567, b)
};

active<Consumerc[] = {
active<Consumer>(891, "I am a Consumer!", b),
active<Consumer>(345, b),
active<Consumer>(678, b)
};

std::size_t i;

std::puts("-----------------------");

for (i = 0; i < ARRAY_DEPTH(p); ++i) {
std::printf("p[%u].m_id == %d\n", i, p[i].object.m_id);
std::printf("p[%u].m_name == %s\n----\n",
i, p[i].object.m_name.c_str());
}

putchar('\n');

for (i = 0; i < ARRAY_DEPTH(c); ++i) {
std::printf("c[%u].m_id == %d\n", i, c[i].object.m_id);
std::printf("c[%u].m_name == %s\n----\n",
i, c[i].object.m_name.c_str());
}

std::puts("-----------------------");
}
std::puts("\n\npress <ENTERto exit...");
std::getchar();
return 0;
}

__________________________________________________ _____________________

This code compiles perfectly fine with no warnings on GCC, Comeau, VC++ 8/9
and EDG/C++.
Can any of you spot any undefined behavior? Also, is the code anywhere near
standard C++? Please try and bear with be here. I am NOT a C++ expert...

:^(
Thanks for all of your time! I really do appreciate it.

Jun 27 '08 #4
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:g2**********@news.datemas.de...
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 <ENTERto 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?
I was thinking that the compiler would complain about something like:

"this form of non-aggregate initialization requires a unary constructor"

For some reason I thought I would have to do something like:
#include <cstdio>
#include <string>
int main() {
{
std::string names[3] = {
std::string("One"),
std::string("Two"),
std::string("Three")
};
}
std::puts("\n\npress <ENTERto exit...");
std::getchar();
return 0;
}
This just goes to show you how little I actually know about C++! I am a C
guy. Ouch!
Anyway, here is my next question:

http://groups.google.com/group/comp....4f85b6d588eaf7
Does the code in that post look Kosher?

Jun 27 '08 #5
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:34******************************@comcast.com. ..
[...]
Okay... Here is what I want to be able to do; the following should compile
and run fine:
__________________________________________________ _____________________
/* Active Object
__________________________________________________ ____________*/
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join
>struct active {
[...]
I think that there might be some problems with ambiguity in the active<T>
template constructors for certain usages. Need to think some more on this
aspect... Humm...

};
[...]

Jun 27 '08 #6
Chris Thomasson wrote:
[..]
Okay... Here is what I want to be able to do; the following should
compile and run fine:
__________________________________________________ _____________________
/* Active Object
__________________________________________________ ____________*/
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join struct active {

T object;

struct guard {
T& object;

guard(T& _object) : object(_object) {
(object.*T_fp_start)();
}

~guard() {
(object.*T_fp_join)();
}
};
I don't understand the importance of this 'guard' struct here.
>
active() {
(object.*T_fp_start)();
}
This is rather dangerous. If 'object' is a POD, it is left
uninitialised. If you wanted it default-initilaised, you need to put it
in the initialiser list:

active() : object() {
...
}

otherwise you're trying to call a member function that might want to
access the object's data, which are not in the proper state...
>
[..]
};


/* Sample usage
__________________________________________________ ____________*/
#include <cstdio>
#include <cstddef>
#include <string>

struct Buffer {
Buffer() {
std::printf("(%p)->Buffer::Buffer()\n", (void*)this);
}

~Buffer() {
std::printf("(%p)->Buffer::~Buffer()\n", (void*)this);
}
};
struct Producer {
int const m_id;
std::string const m_name;
Buffer& m_Buffer;

Producer(int const id, Buffer& _Buffer)
The name "_Buffer" is reserved by the implementation for any uses, so
you cannot use it here. I recommend using lower case ('_buffer') or
renaming the argument altogether. All names that begin with an
underscore and a capital letter are reserved.

Same sentiment applies for all occurrences of "_Buffer" below.
: 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.
}

Producer(int const id, char const* name, Buffer& _Buffer)
: m_id(id), m_name(name), m_Buffer(_Buffer) {
std::printf("(%p)->Producer::Producer()\n", (void*)this);
}

~Producer() {
std::printf("(%p)->Producer::~Producer()\n", (void*)this);
}

void start() {
std::printf("(%p)-void Producer<'%s'>::start() - Buffer(%p)\n",
(void*)this, m_name.c_str(), (void*)&m_Buffer);
}

void join() {
std::printf("(%p)-void Producer::join() - Buffer(%p)\n",
(void*)this, (void*)&m_Buffer);
}
};
struct Consumer {
int const m_id;
std::string const m_name;
Buffer& m_Buffer;

Consumer(int const id, Buffer& _Buffer)
: m_id(id), m_name("Default Consumer"), m_Buffer(_Buffer) {
std::printf("(%p)->Consumer::Consumer()\n", (void*)this);
}

Consumer(int const id, char const* name, Buffer& _Buffer)
: m_id(id), m_name(name), m_Buffer(_Buffer) {
std::printf("(%p)->Consumer::Consumer()\n", (void*)this);
}

~Consumer() {
std::printf("(%p)->Consumer::~Consumer()\n", (void*)this);
}

void start() {
std::printf("(%p)-void Consumer<'%s'>::start() - Buffer(%p)\n",
(void*)this, m_name.c_str(), (void*)&m_Buffer);
}

void join() {
std::printf("(%p)-void Consumer::join() - Buffer(%p)\n",
(void*)this, (void*)&m_Buffer);
}
};
#define ARRAY_DEPTH(mp_this) ( \
sizeof((mp_this)) / sizeof((mp_this)[0]) \
)
You're better off not using a macro for this. Try

template<class T, size_t depth>
size_t array_depth(T (&mp_this)[depth]) {
return depth;
}

(the case has changed, this is not a macro any more).
>

int main() {
{
Buffer b;

active<Producerp[] = {
active<Producer>(123, b),
active<Producer>(456, "Custom Producer", b),
active<Producer>(789, b),
active<Producer>(234, "I am a Producer!", b),
active<Producer>(567, b)
};

active<Consumerc[] = {
active<Consumer>(891, "I am a Consumer!", b),
active<Consumer>(345, b),
active<Consumer>(678, b)
};

std::size_t i;

std::puts("-----------------------");

for (i = 0; i < ARRAY_DEPTH(p); ++i) {
std::printf("p[%u].m_id == %d\n", i, p[i].object.m_id);
std::printf("p[%u].m_name == %s\n----\n",
i, p[i].object.m_name.c_str());
}

putchar('\n');

for (i = 0; i < ARRAY_DEPTH(c); ++i) {
std::printf("c[%u].m_id == %d\n", i, c[i].object.m_id);
std::printf("c[%u].m_name == %s\n----\n",
i, c[i].object.m_name.c_str());
}

std::puts("-----------------------");
}
std::puts("\n\npress <ENTERto exit...");
std::getchar();
return 0;
}

__________________________________________________ _____________________

This code compiles perfectly fine with no warnings on GCC, Comeau, VC++
8/9 and EDG/C++.
So, they are a bit forgiving when it comes to reserved names (and you
got lucky), and you didn't use the default c-tor for your 'active'
template instantiated on a POD...
Can any of you spot any undefined behavior? Also, is the code anywhere
near standard C++? Please try and bear with be here. I am NOT a C++
expert...
Well, the code's close.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #7
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:kO******************************@comcast.com. ..
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:34******************************@comcast.com. ..
[...]
>Okay... Here is what I want to be able to do; the following should
compile and run fine:
_________________________________________________ ______________________
/* Active Object
_________________________________________________ _____________*/
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join
>>struct active {
[...]
I think that there might be some problems with ambiguity in the active<T>
template constructors for certain usages. Need to think some more on this
aspect... Humm...
Well, AFAICT the ambiguity problem only exists because I explicitly defined
the template constructor types as references! Here is a fixed version which
uses no decorations on the template parameter types passed into the
constructor:
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join
struct active {
T object;

struct guard {
T& object;

guard(T& _object) : object(_object) {
(object.*T_fp_start)();
}

~guard() {
(object.*T_fp_join)();
}
};

active() {
(object.*T_fp_start)();
}

template<typename T_p1>
active(T_p1 p1) : object(p1) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2>
active(T_p1 p1, T_p2 p2) : object(p1, p2) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2, typename T_p3>
active(T_p1 p1, T_p2 p2, T_p3 p3)
: object(p1, p2, p3) {
(object.*T_fp_start)();
}

template<typename T_p1, typename T_p2, typename T_p3, typename T_p4>
active(T_p1 p1, T_p2 p2, T_p3 p3, T_p4 p4)
: object(p1, p2, p3, p4) {
(object.*T_fp_start)();
}

// [and on and on for more and more parameters...]

~active() {
(object.*T_fp_join)();
}
};

Jun 27 '08 #8
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:Dd******************************@comcast.com. ..
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:kO******************************@comcast.com. ..
>"Chris Thomasson" <cr*****@comcast.netwrote in message
news:34******************************@comcast.com ...
[...]
>>Okay... Here is what I want to be able to do; the following should
compile and run fine:
________________________________________________ _______________________
/* Active Object
________________________________________________ ______________*/
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join
struct active {
[...]
I think that there might be some problems with ambiguity in the active<T>
template constructors for certain usages. Need to think some more on this
aspect... Humm...

Well, AFAICT the ambiguity problem only exists because I explicitly
defined the template constructor types as references! Here is a fixed
version which uses no decorations on the template parameter types passed
into the constructor:
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join
>struct active {

T object;
[...]

active() {
(object.*T_fp_start)();
}
Need to fix the error:

active() : object() {
(object.*T_fp_start)();
}
[...]

Jun 27 '08 #9
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:g2**********@news.datemas.de...
Chris Thomasson wrote:
>[..]
Okay... Here is what I want to be able to do; the following should
compile and run fine:
_________________________________________________ ______________________
/* Active Object
_________________________________________________ _____________*/
template<
typename T,
void (T::*T_fp_start) () = &T::start,
void (T::*T_fp_join) () = &T::join struct active {

T object;

struct guard {
T& object;

guard(T& _object) : object(_object) {
(object.*T_fp_start)();
}

~guard() {
(object.*T_fp_join)();
}
};

I don't understand the importance of this 'guard' struct here.

Well, its there so the user can so something like:
{
object o;
active<object>::guard g(o);
}
So they can intervene in between the object construction and the invocation
of its start procedure.
>
>>
active() {
(object.*T_fp_start)();
}

This is rather dangerous. If 'object' is a POD, it is left uninitialised.
If you wanted it default-initilaised, you need to put it in the
initialiser list:

active() : object() {
...
}

otherwise you're trying to call a member function that might want to
access the object's data, which are not in the proper state...
OUCH!! :^O


[...]
> Producer(int const id, Buffer& _Buffer)

The name "_Buffer" is reserved by the implementation for any uses, so you
cannot use it here. I recommend using lower case ('_buffer') or renaming
the argument altogether. All names that begin with an underscore and a
capital letter are reserved.

Same sentiment applies for all occurrences of "_Buffer" below.
DOH! Thanks again. What a bone headed mistake. :^(...

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


[...]
>>

#define ARRAY_DEPTH(mp_this) ( \
sizeof((mp_this)) / sizeof((mp_this)[0]) \
)

You're better off not using a macro for this. Try

template<class T, size_t depth>
size_t array_depth(T (&mp_this)[depth]) {
return depth;
}

(the case has changed, this is not a macro any more).
Indeed. The macro is ugly compared to the template.


[...]
>This code compiles perfectly fine with no warnings on GCC, Comeau, VC++
8/9 and EDG/C++.

So, they are a bit forgiving when it comes to reserved names (and you got
lucky), and you didn't use the default c-tor for your 'active' template
instantiated on a POD...
Very lucky! ;^D

>Can any of you spot any undefined behavior? Also, is the code anywhere
near standard C++? Please try and bear with be here. I am NOT a C++
expert...

Well, the code's close.
With all of your excellent help, I think I am going to get this right after
all! I will repost the code in full once I kill all the bugs you so kindly
pointed out:
- Default construct the `active<T>::object' in the `active<T>::active' ctor.
- Honor the reserved namespace rules by eliminating leading underscore and
capital from all the names.
- Remove the macros in favor of templates.
Also, I think I need to remove the explicit reference decorations to the
templated active<Tconstructors. In other words I need to change:

template<typename T_p1>
active(T_p1& p1) : object(p1) {
(object.*T_fp_start)();
}
to:
template<typename T_p1>
active(T_p1 p1) : object(p1) {
(object.*T_fp_start)();
}
This should elude some ambiguity problems I can foresee with the former
definition...

Jun 27 '08 #10
Chris Thomasson wrote:
[..] I think I need to remove the explicit reference decorations to the
templated active<Tconstructors. In other words I need to change:

template<typename T_p1>
active(T_p1& p1) : object(p1) {
(object.*T_fp_start)();
}
to:
template<typename T_p1>
active(T_p1 p1) : object(p1) {
(object.*T_fp_start)();
}
This should elude some ambiguity problems I can foresee with the former
definition...
Those usually work better, yes.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #11
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:g2**********@news.datemas.de...
Chris Thomasson wrote:
>[..] I think I need to remove the explicit reference decorations to the
templated active<Tconstructors. In other words I need to change:

template<typename T_p1>
active(T_p1& p1) : object(p1) {
(object.*T_fp_start)();
}
to:
template<typename T_p1>
active(T_p1 p1) : object(p1) {
(object.*T_fp_start)();
}
This should elude some ambiguity problems I can foresee with the former
definition...

Those usually work better, yes.
Okay good; I thought so. BTW, the main end goal of this `active<T>' template
is going to be an attempt at a full-blown C++ layer over POSIX Threads. I
was thinking of using it to start and join objects which derive from a
threading base class, which will provide the start/join() procedures for
`active<T>' to automatically invoke, in a manner which respects the RAII
idiom. Also, for the syntactic sugar of starting threads. You should be able
to so something like:
class object : public thread_base {
void on_entry() {
// [the thread function];
}
};
int main() {
{
active<objecto[4];
}
return 0;
}
That looks fairly clean to me...

;^)

Jun 27 '08 #12
On Jun 3, 4:18 pm, "Chris Thomasson" <cris...@comcast.netwrote:
"Victor Bazarov" <v.Abaza...@comAcast.netwrote 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 27 '08 #13
Chris Thomasson wrote:
I was thinking that the compiler would complain about something like:

"this form of non-aggregate initialization requires a unary constructor"

For some reason I thought I would have to do something like:
#include <cstdio>
#include <string>
int main() {
{
std::string names[3] = {
std::string("One"),
std::string("Two"),
std::string("Three")
};
}
std::puts("\n\npress <ENTERto exit...");
std::getchar();
return 0;
}
std::string's char* constructor is not explicit. You are actually using
the constructor when you pass char const* data into your array construction.
Jun 27 '08 #14
<ja************@gmail.comwrote in message
news:f7**********************************@r66g2000 hsg.googlegroups.com...
On Jun 3, 4:18 pm, "Chris Thomasson" <cris...@comcast.netwrote:
>"Victor Bazarov" <v.Abaza...@comAcast.netwrote 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.
Even a function pointer?

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 27 '08 #15
On Jun 3, 8:09 pm, "Chris Thomasson" <cris...@comcast.netwrote:
<jason.cipri...@gmail.comwrote 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 27 '08 #16
<ja************@gmail.comwrote in message
news:e5**********************************@56g2000h sm.googlegroups.com...
On Jun 3, 8:09 pm, "Chris Thomasson" <cris...@comcast.netwrote:
><jason.cipri...@gmail.comwrote 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. :-)
I misinterpreted you. :^o

Jun 27 '08 #17
On Jun 3, 10:02 pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
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:ja*********@gmail.com
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
Jun 27 '08 #18
On Jun 4, 1:36 am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.comwrote:
On Jun 3, 4:18 pm, "Chris Thomasson" <cris...@comcast.netwrote:
"Victor Bazarov" <v.Abaza...@comAcast.netwrote 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:ja*********@gmail.com
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
Jun 27 '08 #19
James Kanze wrote:
On Jun 4, 1:36 am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.comwrote:
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 27 '08 #20
On Jun 4, 5:16 am, James Kanze <james.ka...@gmail.comwrote:
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 27 '08 #21
On Jun 4, 5:43 pm, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.comwrote:
James Kanze wrote:
On Jun 4, 1:36 am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.comwrote:
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:ja*********@gmail.com
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
Jun 27 '08 #22
On Jun 4, 5:57 pm, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.comwrote:
On Jun 4, 5:16 am, James Kanze <james.ka...@gmail.comwrote:
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:ja*********@gmail.com
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
Jun 27 '08 #23
"James Kanze" <ja*********@gmail.comwrote in message
news:07**********************************@r66g2000 hsg.googlegroups.com...
On Jun 3, 10:02 pm, Victor Bazarov <v.Abaza...@comAcast.netwrote:
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.
Right. Thats what I thought.

This sort of thing is why good programmers eschew printf and
company.
;^)
Well, I use `printf', or I should correctly say `std::printf', simply
because I am truly a C programmer at heart.

:^o

Jun 27 '08 #24
On 4 Jun, 17:57, "jason.cipri...@gmail.com" <jason.cipri...@gmail.com>
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
Jun 27 '08 #25
On Jun 5, 4:28 am, Triple-DES <DenPlettf...@gmail.comwrote:
On 4 Jun, 17:57, "jason.cipri...@gmail.com" <jason.cipri...@gmail.com>
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 27 '08 #26

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: lawrence | last post by:
I have a string which I want to send to eval(). How can I test it ahead of time to make sure it is valid code? I don't want to send it to eval and get parse errors. I want to do something like...
1
by: carl bloc | last post by:
Have this much done but need help with this bit of code: allow user to modify existing draw data. I think I need a counter to give week numbers so the user can select a week number rather than a...
23
by: James Aguilar | last post by:
Someone showed me something today that I didn't understand. This doesn't seem like it should be valid C++. Specifically, I don't understand how the commas are accepted after the function...
109
by: Andrew Thompson | last post by:
It seems most people get there JS off web sites, which is entirely logical. But it is also a great pity since most of that code is of such poor quality. I was looking through the JS FAQ for any...
2
by: rked | last post by:
I get nameSPAN1 is undefined when I place cursor in comments box.. <%@ LANGUAGE="VBScript" %> <% DIM ipAddress ipAddress=Request.Servervariables("REMOTE_HOST") %> <html> <head> <meta...
40
by: Neo The One | last post by:
I think C# is forcing us to write more code by enforcing a rule that can be summarized as 'A local variable must be assgined *explicitly* before reading its value.' If you are interested in what...
3
by: Jamie Risk | last post by:
I'm attempting to improve some serially executing code (that uses the SerialPort class) bogging Windows down when it runs. To do the 'antibogging' I'm following the example from MSDN...
1
by: jjmontreal | last post by:
I am trying to run this code in a form when a user double clicks in a particular field. I am unsure how I should do it since it uses 2 text files, one to generate and the other to store to eleminate...
4
by: Miha V | last post by:
Hi! We are using ASMX web service with WSE (we're using WS-Addressing) and IIS returns HTTP status code 200 even if XML is malformed (it can contain illegal characters in it). The request...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.