Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #4726 > unrolled thread

this cast to const char*

Started by"Gernot Frisch" <me@privacy.net>
First post2011-05-05 19:27 +0200
Last post2011-05-09 09:40 -0700
Articles 10 on this page of 30 — 15 participants

Back to article view | Back to comp.lang.c++


Contents

  this cast to const char* "Gernot Frisch" <me@privacy.net> - 2011-05-05 19:27 +0200
    Re: this cast to const char* Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-05-05 19:39 +0200
      Re: this cast to const char* "Balog Pal" <pasa@lib.hu> - 2011-05-06 01:11 +0200
        Re: this cast to const char* Marcel Müller <news.5.maazl@spamgourmet.org> - 2011-05-06 01:54 +0200
          Re: this cast to const char* m0shbear <andrey.vul@gmail.com> - 2011-05-05 17:59 -0700
            Re: this cast to const char* James Kanze <james.kanze@gmail.com> - 2011-05-08 07:08 -0700
              Re: this cast to const char* m0shbear <andrey.vul@gmail.com> - 2011-05-08 17:03 -0700
          Re: this cast to const char* "Balog Pal" <pasa@lib.hu> - 2011-05-06 20:15 +0200
          Re: this cast to const char* James Kanze <james.kanze@gmail.com> - 2011-05-08 07:05 -0700
      Re: this cast to const char* James Kanze <james.kanze@gmail.com> - 2011-05-08 07:02 -0700
    Re: this cast to const char* Felix Bytow <felix.bytow@informatik.tu-chemnitz.de> - 2011-05-05 19:40 +0200
      Re: this cast to const char* Öö Tiib <ootiib@hot.ee> - 2011-05-05 10:52 -0700
    Re: this cast to const char* Öö Tiib <ootiib@hot.ee> - 2011-05-05 10:44 -0700
    Re: this cast to const char* gwowen <gwowen@gmail.com> - 2011-05-05 10:50 -0700
      Re: this cast to const char* Öö Tiib <ootiib@hot.ee> - 2011-05-05 10:58 -0700
        Re: this cast to const char* "Bo Persson" <bop@gmb.dk> - 2011-05-05 20:21 +0200
        Re: this cast to const char* gwowen <gwowen@gmail.com> - 2011-05-05 11:27 -0700
          Re: this cast to const char* Öö Tiib <ootiib@hot.ee> - 2011-05-05 11:37 -0700
            Re: this cast to const char* gwowen <gwowen@gmail.com> - 2011-05-05 22:28 -0700
              Re: this cast to const char* Öö Tiib <ootiib@hot.ee> - 2011-05-06 03:55 -0700
                Re: this cast to const char* "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> - 2011-05-06 13:25 +0200
                  Re: this cast to const char* Öö Tiib <ootiib@hot.ee> - 2011-05-06 06:22 -0700
    Re: this cast to const char* Joshua Maurice <joshuamaurice@gmail.com> - 2011-05-05 22:47 -0700
    Re: this cast to const char* Goran <goran.pusic@gmail.com> - 2011-05-06 06:59 -0700
      Re: this cast to const char* Pete Becker <pete@versatilecoding.com> - 2011-05-06 10:17 -0400
        Re: this cast to const char* James Kanze <james.kanze@gmail.com> - 2011-05-08 07:13 -0700
      Re: this cast to const char* "Gernot Frisch" <me@privacy.net> - 2011-05-09 10:38 +0200
        Re: this cast to const char* Leigh Johnston <leigh@i42.co.uk> - 2011-05-09 13:03 +0100
          Re: this cast to const char* Leigh Johnston <leigh@i42.co.uk> - 2011-05-09 17:51 +0100
        Re: this cast to const char* Öö Tiib <ootiib@hot.ee> - 2011-05-09 09:40 -0700

Page 2 of 2 — ← Prev page 1 [2]


#4769

From"Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com>
Date2011-05-06 13:25 +0200
Message-ID<iq0l4l$ok7$1@dont-email.me>
In reply to#4768
* Öö Tiib, on 06.05.2011 12:55:
> On May 6, 8:28 am, gwowen<gwo...@gmail.com>  wrote:
>> On May 5, 7:37 pm, Öö Tiib<oot...@hot.ee>  wrote:
>>
>>> Hmm ... really? Where does standard say that POD base sub-object when
>>> used with single inheritance should be located at very start of object
>>> of derived class?
>>
>> The standard doesn't.  Every single implementation that is or ever
>> will be in existence does.
>
> Uhh. I never dare to be so absolute about C++ compilers. Here i can
> even provide evidence of opposite with a compiler manufactured by
> CString creators themselves.
>
> <code>
>   // WARNING: this is meant as example
>   // of really awful coding practices
>   #include<iostream>
>   #include<cstdio>
>
>   struct Pod { int p; };
>
>   class DerivedFromPod
>       : public Pod // single derived
>   {
>   public:
>       DerivedFromPod() { p=42; d=0; };
>       virtual ~DerivedFromPod() {};
>   private:
>       int d;
>   };
>
>   int main()
>   {
>       DerivedFromPod* der = new DerivedFromPod();
>       Pod* pod = der; // implicit cast here
>
>       std::cout<<  "der is at: "<<  der
>                 <<  " pod is at: "<<  pod<<  std::endl;
>       printf( "ints from der %d, %d \n", *der );
>       printf( "ints from pod %d, %d \n", *pod );
>       delete der;
>   }
> </code>
>
> Compiling it for Win32 MS compiler Visual C++ 0.9 (bundled in VS
> "CString" 2008 Professional)
> Running it produces something like:
>
> der is at: 00356940 pod is at: 00356944
> ints from der 4290588, 42
> ints from pod 42, -242263521
>
> So there we are with your "Every single implementation that is or ever
> will be in existence does".

One of the reasons why one should not reinterpret_cast up or down a class 
hierarchy, but use static_cast which adjusts pointer values appropriately.

That said, I think the original discussion had as an implicit assumption that 
one would not introduce virtual methods in derived class.

And in that case the compiler would have to be perverse to start changing the 
layout. I'm not sure but I think that for C++0x the compiler would have to stop 
such practice, if it ever did. I.e., considerations of layout are not inherently 
inappropriate, but one needs to be very careful (like, no virtuals).


Cheers,

- Alf

-- 
blog at <url: http://alfps.wordpress.com>

[toc] | [prev] | [next] | [standalone]


#4774

FromÖö Tiib <ootiib@hot.ee>
Date2011-05-06 06:22 -0700
Message-ID<7ec83b98-9241-4195-8911-cf3d444604e5@v8g2000yqb.googlegroups.com>
In reply to#4769
On May 6, 2:25 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
+use...@gmail.com> wrote:
>
> That said, I think the original discussion had as an implicit assumption that
> one would not introduce virtual methods in derived class.

One should not assume such things implicitly. Exceptional design
constraints should be always documented or if possible enforced with
static asserts. Otherwise someone maintains the code and breaks it. As
result some printf (possibly called in rare conditions) starts to
write utter crap or to crash.

> And in that case the compiler would have to be perverse to start changing the
> layout. I'm not sure but I think that for C++0x the compiler would have to stop
> such practice, if it ever did. I.e., considerations of layout are not inherently
> inappropriate, but one needs to be very careful (like, no virtuals).

I think that such "undefined behavior" that works predictably and
predictability is portable can be documented by standard. I have no
real need for it since i avoid using the UB anyway but someone may
benefit from it.

For example if the location of some hidden and undocumented 'vtable
const&' members is anyway similar on most major implementations then
why not to document some std::vtable<T> const& as a real implicit
member of every class that has virtual functions?

If then also to specify the memory layout of a T& (that is internally
a T* const anyway on most implementations) then every class would be
layout compatible as a result.

Like i said i don't need to dig in there and would object someone
really using such deep internals but some people (who want to
implement reflection for example) might benefit. It does not anyway
justify usage of the structured objects as arguments for a printf that
is quite awful (confusing and error-prone) practice.

[toc] | [prev] | [next] | [standalone]


#4757

FromJoshua Maurice <joshuamaurice@gmail.com>
Date2011-05-05 22:47 -0700
Message-ID<d53aadd6-6420-4988-8058-01ae717dc234@r33g2000prh.googlegroups.com>
In reply to#4726
On May 5, 10:27 am, "Gernot Frisch" <m...@privacy.net> wrote:
> Hi,
>
> with "MFC" I can do:
> CString str(_T("test"); printf("%s", str); // prints "test"
>
> With my own string class, however, there seems to be a 4 byte "header"
> before the string data.
>
> I have the member >const TCHAR* m_data;< as the first member of my string
> class.
>
> How does MS doe this?

I just thought I'd pipe in that my own company has done this as well
with its own custom string class, hacked it just like CString so it
works in printf. I hate it. The code will test and work on windows,
but blow up as soon as it's tried on a non-windows platform, and as
most developers are windows based, including myself, this is quite
annoying. I wish they never had a cast operator in their string class,
and I wish they didn't use C-vararg printf style functions. But they
do, and I suffer. Heed the warnings from this thread.

[toc] | [prev] | [next] | [standalone]


#4776

FromGoran <goran.pusic@gmail.com>
Date2011-05-06 06:59 -0700
Message-ID<763ee119-dff9-40a9-9c70-69708aa13a65@18g2000prd.googlegroups.com>
In reply to#4726
On May 5, 7:27 pm, "Gernot Frisch" <m...@privacy.net> wrote:
> Hi,
>
> with "MFC" I can do:
> CString str(_T("test"); printf("%s", str); // prints "test"
>
> With my own string class, however, there seems to be a 4 byte "header"
> before the string data.
>
> I have the member >const TCHAR* m_data;< as the first member of my string
> class.
>
> How does MS doe this?

Luck (well, cheating). First of all, as said, passing non-pod is UB.
What actually happens is that your string is passed to printf as a
POD. But CString class is made in such a way that "this" is also a
pointer to the first character (there's more to CString than a
pointer, and you don't want to know that ;-).

So... Your code has an error, but you don't see it. To make code error-
free, do:

printf("%s", static_cast<LPCTSTR>(yourstring)));

Or, to avoid casting-induced eyesore, apply some simple DRY:

inline LPCTSTR chars(const CString& s) { return s; }

and then

printf("%s", chars(yourstring));

Had you compiled for Unicode, your code would have not worked. With
Unicode on windows, use _tprintf.

Finally, the only way to trick printf with your type is the trick MS
used. DONT DO THAT! ;-)

Goran.

[toc] | [prev] | [next] | [standalone]


#4777

FromPete Becker <pete@versatilecoding.com>
Date2011-05-06 10:17 -0400
Message-ID<201105061017516095-pete@versatilecodingcom>
In reply to#4776
On 2011-05-06 09:59:31 -0400, Goran said:

> On May 5, 7:27 pm, "Gernot Frisch" <m...@privacy.net> wrote:
>> Hi,
>> 
>> with "MFC" I can do:
>> CString str(_T("test"); printf("%s", str); // prints "test"
>> 
>> With my own string class, however, there seems to be a 4 byte "header"
>> before the string data.
>> 
>> I have the member >const TCHAR* m_data;< as the first member of my string
>> class.
>> 
>> How does MS doe this?
> 
> Luck (well, cheating). First of all, as said, passing non-pod is UB.
> What actually happens is that your string is passed to printf as a
> POD. But CString class is made in such a way that "this" is also a
> pointer to the first character (there's more to CString than a
> pointer, and you don't want to know that ;-).
> 
> So... Your code has an error,

No, it doesn't. "Undefined behavior" means only that the C++ standard 
doesn't tell you what the code does. There's nothing preventing a 
compiler from defining the behavior, and there's nothing inherently 
wrong with relying on implementation-specific behavior.

-- 
  Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The 
Standard C++ Library Extensions: a Tutorial and Reference 
(www.petebecker.com/tr1book)

[toc] | [prev] | [next] | [standalone]


#4807

FromJames Kanze <james.kanze@gmail.com>
Date2011-05-08 07:13 -0700
Message-ID<f4331d37-e147-4f62-93af-4bd91d7c5129@a18g2000yqj.googlegroups.com>
In reply to#4777
On May 6, 3:17 pm, Pete Becker <p...@versatilecoding.com> wrote:
> On 2011-05-06 09:59:31 -0400, Goran said:
> >> I have the member >const TCHAR* m_data;< as the first member of my string
> >> class.

> >> How does MS doe this?

> > Luck (well, cheating). First of all, as said, passing non-pod is UB.
> > What actually happens is that your string is passed to printf as a
> > POD. But CString class is made in such a way that "this" is also a
> > pointer to the first character (there's more to CString than a
> > pointer, and you don't want to know that ;-).

> > So... Your code has an error,

> No, it doesn't. "Undefined behavior" means only that the C++ standard
> doesn't tell you what the code does. There's nothing preventing a
> compiler from defining the behavior, and there's nothing inherently
> wrong with relying on implementation-specific behavior.

And if you're using CString (instead of std::string), you're
already very implementation specific, so you might as well take
the good (assuming you consider being able to use printf good)
with the bad.

--
James Kanze

[toc] | [prev] | [next] | [standalone]


#4828

From"Gernot Frisch" <me@privacy.net>
Date2011-05-09 10:38 +0200
Message-ID<92pnfkFtb8U1@mid.individual.net>
In reply to#4776

> with "MFC" I can do:
> CString str(_T("test"); printf("%s", str); // prints "test"

Hi,

problem is: We want to replace CString in an existing project, and there are 
lots of the above situations.

Now, My string class does not have any virtual member functions. What else 
could it be? I can't find how MS did that trick.

Bye,
-Gernot

[toc] | [prev] | [next] | [standalone]


#4832

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-05-09 13:03 +0100
Message-ID<OJydnSAd8MGURVrQnZ2dnUVZ7oWdnZ2d@giganews.com>
In reply to#4828
On 09/05/2011 09:38, Gernot Frisch wrote:
>
>
>> with "MFC" I can do:
>> CString str(_T("test"); printf("%s", str); // prints "test"
>
> Hi,
>
> problem is: We want to replace CString in an existing project, and there
> are lots of the above situations.
>
> Now, My string class does not have any virtual member functions. What
> else could it be? I can't find how MS did that trick.
>
> Bye,
> -Gernot

The solution is to do things properly rather than rely on undefined 
behaviour as Microsoft are doing:

printf("%s", static_cast<const char*>(yourStringObject)); // provide a 
const char* conversion operator in your string class.

Even better would be to stop using the old fashioned printf all together. :)

/Leigh

[toc] | [prev] | [next] | [standalone]


#4835

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-05-09 17:51 +0100
Message-ID<K9idnZTVmtsLhlXQnZ2dnUVZ8mudnZ2d@giganews.com>
In reply to#4832
On 09/05/2011 13:03, Leigh Johnston wrote:
> On 09/05/2011 09:38, Gernot Frisch wrote:
>>
>>
>>> with "MFC" I can do:
>>> CString str(_T("test"); printf("%s", str); // prints "test"
>>
>> Hi,
>>
>> problem is: We want to replace CString in an existing project, and there
>> are lots of the above situations.
>>
>> Now, My string class does not have any virtual member functions. What
>> else could it be? I can't find how MS did that trick.
>>
>> Bye,
>> -Gernot
>
> The solution is to do things properly rather than rely on undefined
> behaviour as Microsoft are doing:
>
> printf("%s", static_cast<const char*>(yourStringObject)); // provide a
> const char* conversion operator in your string class.
>
> Even better would be to stop using the old fashioned printf all
> together. :)

Actually Öö Tiib is right: adding a c_str() member function is 
preferable to my slightly ugly conversion operator suggestion.

/Leigh

[toc] | [prev] | [next] | [standalone]


#4834

FromÖö Tiib <ootiib@hot.ee>
Date2011-05-09 09:40 -0700
Message-ID<c9e069f3-b039-4ec0-aeaa-64c89501af54@k22g2000yqh.googlegroups.com>
In reply to#4828
On May 9, 11:38 am, "Gernot Frisch" <m...@privacy.net> wrote:
> > with "MFC" I can do:
> > CString str(_T("test"); printf("%s", str); // prints "test"
>
> Hi,
>
> problem is: We want to replace CString in an existing project, and there are
> lots of the above situations.

Can't you just add member 'char const* c_str()' to your string?
Then

 CString str(_T("test")); printf("%s", str);

becomes

 YourString str("test"); printf("%s", str.c_str());

If it is hard to find the places where to add that '.c_str()' then
download g++ and try to compile , it will warn such places.

> Now, My string class does not have any virtual member functions. What else
> could it be? I can't find how MS did that trick.

MS CString is seemingly header-only. How can it be that you can not
find it? If you can't understand the trick then ... do not use evil
magic you can't understand.

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c++


csiph-web