Connecting Tech Pros Worldwide Help | Site Map

Data initialization (is this correct?)

mathieu
Guest
 
Posts: n/a
#1: May 27 '06
I would like to know if the following operation on s2 is legal or not.
And if not what should I do instead (my data member are declared at the
begining of the struct).
I am pretty sure this is illegal, but I would like to avoid duplicating
the logic that take place when initializing s1.

Thanks for your help.
Mathieu

(*)
#include <iostream>

struct String
{
char Internal[4+1];
void Print() {
std::cout << Internal << std::endl;
}
};

int main()
{
String s1 = {"019Y"}; // give compiler error if too large
s1.Print();

String s2;
char array[] = "123D";
s2 = reinterpret_cast<String&>( array ); // is this legal
s2.Print();
return 0;
}

Jerry Coffin
Guest
 
Posts: n/a
#2: May 27 '06

re: Data initialization (is this correct?)


In article <1148696512.476379.294630
@i39g2000cwa.googlegroups.com>,
mathieu.malaterre@gmail.com says...

[ ... ]
[color=blue]
> String s2;
> char array[] = "123D";
> s2 = reinterpret_cast<String&>( array ); // is this legal[/color]

That depends on what you mean by "legal". It doesn't give
defined results, if that's what you mean.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Luke Meyers
Guest
 
Posts: n/a
#3: May 27 '06

re: Data initialization (is this correct?)


mathieu wrote:[color=blue]
> I would like to know if the following operation on s2 is legal or not.
> And if not what should I do instead (my data member are declared at the
> begining of the struct).
>
> struct String
> {
> char Internal[4+1];
> void Print() {
> std::cout << Internal << std::endl;
> }
> };[/color]

Kind of an odd struct -- is this something you're actually attempting
to use, or a dumbed-down example? If the latter, fine. If the
former... reconsider.
[color=blue]
> String s1 = {"019Y"}; // give compiler error if too large
> s1.Print();
>
> String s2;
> char array[] = "123D";
> s2 = reinterpret_cast<String&>( array ); // is this legal
>
> I am pretty sure this is illegal[/color]

It's not technically illegal, but as with any use of reinterpret_cast,
there is no guarantee whatsoever as to what the result could be. It's
100% implementation-defined and non-portable. Whatever you're trying
to achieve, reinterpret_cast is not the way.
[color=blue]
> but I would like to avoid duplicating
> the logic that take place when initializing s1.[/color]

Could you explain what you mean by this? There's not really any logic
to speak of. Are you attempting to optimize for speed? Avoid code
duplication? I don't think either is happening here.

Luke

Tomás
Guest
 
Posts: n/a
#4: May 27 '06

re: Data initialization (is this correct?)


mathieu posted:

[color=blue]
> s2 = reinterpret_cast<String&>( array ); // is this legal[/color]


Yes, it's perfectly okay. I'll show you why. Firstly the Standard
guarantees that the following is pefectly legal:

struct Monkey {
int array[10];
};

int main()
{
Monkey obj;

int (&array)[10] =
reinterpret_cast<int (&)[10]>(obj);

array[3] = 7;
}


Therefore the reverse must be true:


struct Monkey {
int array[10];
};

int main()
{
int array[10];

Monkey &monkey =
reinterpret_cast<Monkey &>(array);

monkey.array[3] = 7;
}


However, this only holds true for a POD. Here's the relevant passage from
the Standard:

9.2 p17: A pointer to a POD-struct, suitably converted using a
reinterpret_cast, points to its initial member (of if that member is a bit-
field, then to the unit in which it resides) and vice versa."


-Tomás
Tomás
Guest
 
Posts: n/a
#5: May 27 '06

re: Data initialization (is this correct?)


Jerry Coffin posted:
[color=blue]
> In article <1148696512.476379.294630
> @i39g2000cwa.googlegroups.com>,
> mathieu.malaterre@gmail.com says...
>
> [ ... ]
>[color=green]
>> String s2;
>> char array[] = "123D";
>> s2 = reinterpret_cast<String&>( array ); // is this legal[/color]
>
> That depends on what you mean by "legal". It doesn't give
> defined results, if that's what you mean.[/color]

I disagree:

9.2 p17: "A pointer to a POD-struct, suitably converted using a
reinterpret_cast, points to its initial member (of if that member is a bit-
field, then to the unit in which it resides) and vice versa."

I demonstrate exploitation of this feature elsewhere in the thread.

-Tomás
Jerry Coffin
Guest
 
Posts: n/a
#6: May 27 '06

re: Data initialization (is this correct?)


In article <O50eg.9610$j7.306562@news.indigo.ie>,
No.Email@Address says...

[ ... ]
[color=blue]
> I disagree:
>
> 9.2 p17: "A pointer to a POD-struct, suitably converted using a
> reinterpret_cast, points to its initial member (of if that member is a bit-
> field, then to the unit in which it resides) and vice versa."[/color]

Rereading his definition of String, you're right. I
apologize for the misinformation.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Roland Pibinger
Guest
 
Posts: n/a
#7: May 27 '06

re: Data initialization (is this correct?)


On Sat, 27 May 2006 17:33:39 GMT, "Tomás" <No.Email@Address> wrote:[color=blue]
>mathieu posted:[color=green]
>> s2 = reinterpret_cast<String&>( array ); // is this legal[/color]
>
>Yes, it's perfectly okay. I'll show you why. Firstly the Standard
>guarantees that the following is pefectly legal:
>
>struct Monkey {
> int array[10];
>};
>
>int main()
>{
> Monkey obj;
>
> int (&array)[10] =
> reinterpret_cast<int (&)[10]>(obj);
>
> array[3] = 7;
>}
>
>
>Therefore the reverse must be true:[/color]

Nope. It probably 'works' in most cases but it's not correct C++, not
even for PODs.

Best wishes,
Roland Pibinger

Tomás
Guest
 
Posts: n/a
#8: May 27 '06

re: Data initialization (is this correct?)


Roland Pibinger posted:

[color=blue][color=green]
>>Therefore the reverse must be true:[/color]
>
> Nope. It probably 'works' in most cases but it's not correct C++, not
> even for PODs.[/color]


Care to elaborate on that?


Here's my logic:

We start off with a simple POD as follows:

struct Monkey { int array[10]; };


We can convert a "Monkey*" to a "int (*)[10]", and we can subsequently
use that pointer to access the array, i.e.:

Monkey obj;

int (*array)[10] = reinterpret_cast<int (*)[10]>(&obj);

(*array)[3] = 72;


Why do you suppose that the opposite cannot be done:

int array[10];

Monkey *p_monkey =
reinterpret_cast<Monkey*>( &array );

p_monkey->array[3] = 56;


-Tomás
Roland Pibinger
Guest
 
Posts: n/a
#9: May 27 '06

re: Data initialization (is this correct?)


On Sat, 27 May 2006 20:10:37 GMT, "Tomás" <No.Email@Address> wrote:[color=blue]
>Roland Pibinger posted:
>[color=green][color=darkred]
>>>Therefore the reverse must be true:[/color]
>>
>> Nope. It probably 'works' in most cases but it's not correct C++, not
>> even for PODs.[/color]
>
>Care to elaborate on that?
>
>Here's my logic:
>We start off with a simple POD as follows:
>
> struct Monkey { int array[10]; };
>
>We can convert a "Monkey*" to a "int (*)[10]", and we can subsequently
>use that pointer to access the array, i.e.:[/color]

Ok
[color=blue]
> Monkey obj;
> int (*array)[10] = reinterpret_cast<int (*)[10]>(&obj);
> (*array)[3] = 72;
>
>Why do you suppose that the opposite cannot be done:
>
> int array[10];
> Monkey *p_monkey =
> reinterpret_cast<Monkey*>( &array );
> p_monkey->array[3] = 56;[/color]

You can only convert beetween a POD-stuct and its first data member
(and vice versa), not between an arbitrary 'int[10]' and 'struct
Monkey'. Monkey may be larger than array: sizeof (Monkey) >= sizeof
(array). Even alignment restricitions might be different (unlikely).

Best wishes,
Roland Pibinger
Tomás
Guest
 
Posts: n/a
#10: May 27 '06

re: Data initialization (is this correct?)


Roland Pibinger posted:

[color=blue]
> You can only convert beetween a POD-stuct and its first data member
> (and vice versa), not between an arbitrary 'int[10]' and 'struct
> Monkey'. Monkey may be larger than array: sizeof (Monkey) >= sizeof
> (array).[/color]


I don't see how this would be a problem if we only use the resultant
Monkey* to access the struct's first member.

[color=blue]
> Even alignment restricitions might be different (unlikely).[/color]


Interesting point. I wonder if that's possible... ?


-Tomás
mathieu
Guest
 
Posts: n/a
#11: May 29 '06

re: Data initialization (is this correct?)



Luke Meyers wrote:[color=blue]
> Kind of an odd struct -- is this something you're actually attempting
> to use, or a dumbed-down example? If the latter, fine. If the
> former... reconsider.
>[/color]

If you have nothing to do for memorial day here is the full source:
http://svn.sourceforge.net/viewcvs.c...?view=annotate
Comments welcome.
[color=blue]
> It's not technically illegal, but as with any use of reinterpret_cast,
> there is no guarantee whatsoever as to what the result could be. It's
> 100% implementation-defined and non-portable. Whatever you're trying
> to achieve, reinterpret_cast is not the way.[/color]

I simply need to fill in my structure at run time. The only other way I
can see is encapsulate all my templates (see link above) in one class
that would have a giant switch depending on the templates argument.
It's always the same problem interfacing templated code with run time
information.
[color=blue]
> Could you explain what you mean by this? There's not really any logic
> to speak of. Are you attempting to optimize for speed? Avoid code
> duplication? I don't think either is happening here.[/color]

I liked the fact the *compiler* was telling me something is wrong, such
as array is too big/small, not the right type. The idea was that I
could describe the whole DICOM standard, and then try to compile it, if
it does not compile the standard has a problem :)

Thanks for reading,
Mathieu

mathieu
Guest
 
Posts: n/a
#12: May 29 '06

re: Data initialization (is this correct?)



Roland Pibinger wrote:
[color=blue]
> You can only convert beetween a POD-stuct and its first data member
> (and vice versa), not between an arbitrary 'int[10]' and 'struct
> Monkey'. Monkey may be larger than array: sizeof (Monkey) >= sizeof
> (array). Even alignment restricitions might be different (unlikely).[/color]

Oh I think I understand what you are saying. For instance:

struct Monkey {
int a;
int b;
};

the standard does not say anything on how to access Monkey.b. Is this
correct.
Therefore the standard does not say anything for an array, I can only
change the very first data member:

struct Monkey {
int array[10];
};

in this case: Monkey.array[0].

Thanks for your help,
Mathieu

Tomás
Guest
 
Posts: n/a
#13: May 29 '06

re: Data initialization (is this correct?)


mathieu posted:

[color=blue]
> Therefore the standard does not say anything for an array, I can only
> change the very first data member:
>
> struct Monkey {
> int array[10];
> };[/color]


No, the entire array is counted as "one object". However it does have
"sub-objects"... just like how an "std::string" is thought of as one
object, even though it may have a few sub-objects. To take it to an
extreme:


struct Monkey {
int a[10];
double b;
void *p;
};

struct Ape {
Monkey monkey;
char k;
float s;
};

struct Lizard {
Ape ape;
char a;
char n;
};

int main()
{
Lizard obj;

int (&array)[10] = reinterpret_cast<int (&)[10]>(obj);

array[3] = 37;
}


Or the inheritance way works aswell

struct Monkey { ...
struct Ape : Monkey { ...
struct Lizard : Ape { ...

Lizard obj;

int (&array)[10] = reinter...


Just so long as we're dealing with POD's.

-Tomás

-Tomás
Luke Meyers
Guest
 
Posts: n/a
#14: May 29 '06

re: Data initialization (is this correct?)


mathieu wrote:[color=blue]
> If you have nothing to do for memorial day here is the full source:
> http://svn.sourceforge.net/viewcvs.c...?view=annotate
> Comments welcome.[/color]

That's funny... looking at that source, "comments welcome" is exactly
what I was thinking ;). Sorry, not enough time for guesswork -- though
if you'd care to point out the problematic section and explain what
you're trying to do in words, maybe you'll get the help you want.
[color=blue][color=green]
> > Whatever you're trying
> > to achieve, reinterpret_cast is not the way.[/color]
>
> I simply need to fill in my structure at run time.[/color]

You mean like a constructor does?
[color=blue]
> The only other way I
> can see is encapsulate all my templates (see link above) in one class
> that would have a giant switch depending on the templates argument.[/color]

That sounds like a pretty ugly way to solve... some problem. What's
the problem you're trying to solve? All you've said is "fill in my
structure at run time," which sounds like a description of what
constructors do. What is it that you're trying to accomplish that you
feel you can't do with a constructor?
[color=blue]
> It's always the same problem interfacing templated code with run time
> information.[/color]

There are definitely complexities involved. I'm confused, though,
because your question had nothing to do with templates.
[color=blue][color=green]
> > Could you explain what you mean by this? There's not really any logic
> > to speak of. Are you attempting to optimize for speed? Avoid code
> > duplication? I don't think either is happening here.[/color]
>
> I liked the fact the *compiler* was telling me something is wrong, such
> as array is too big/small, not the right type. The idea was that I
> could describe the whole DICOM standard, and then try to compile it, if
> it does not compile the standard has a problem :)[/color]

That sounds very interesting -- what does it have to do with my
question? All I asked is what you meant about how you "would like to
avoid duplicating the logic that take [sic] place when initializing
s1."

Luke

mathieu
Guest
 
Posts: n/a
#15: May 31 '06

re: Data initialization (is this correct?)


Luke Meyers wrote:[color=blue]
> mathieu wrote:[color=green]
> > If you have nothing to do for memorial day here is the full source:
> > http://svn.sourceforge.net/viewcvs.c...?view=annotate
> > Comments welcome.[/color]
>
> That's funny... looking at that source, "comments welcome" is exactly
> what I was thinking ;). Sorry, not enough time for guesswork -- though
> if you'd care to point out the problematic section and explain what
> you're trying to do in words, maybe you'll get the help you want.[/color]

Ok I'll try to summarize my problem with this simple one.
struct MyInt {
int Internal[4];
};
int main()
{
MyInt i = { 0,1,2,3 };
// MyInt i = { 0,1,2,3,4 }; // should throw an error
return 0;
}

Please describe a constructor that would do this exact job. I could not
figure out a way to throw an error when there are too many initializers
(see commented line).

Thanks
Mathieu

Closed Thread