Data initialization (is this correct?)

M

mathieu

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;
}
 
J

Jerry Coffin

@i39g2000cwa.googlegroups.com>,
(e-mail address removed) says...

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

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

Luke Meyers

mathieu said:
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;
}
};

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

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.
but I would like to avoid duplicating
the logic that take place when initializing s1.

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
 
T

Tomás

mathieu posted:

s2 = reinterpret_cast<String&>( array ); // is this legal


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
 
T

Tomás

Jerry Coffin posted:
@i39g2000cwa.googlegroups.com>,
(e-mail address removed) says...

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

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

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
 
J

Jerry Coffin

[ ... ]
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."

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

Roland Pibinger

mathieu posted:
s2 = reinterpret_cast<String&>( array ); // is this legal

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:

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

Best wishes,
Roland Pibinger
 
T

Tomás

Roland Pibinger posted:

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


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
 
R

Roland Pibinger

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

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

Ok
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;

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
 
T

Tomás

Roland Pibinger posted:

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


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

Even alignment restricitions might be different (unlikely).


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


-Tomás
 
M

mathieu

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

If you have nothing to do for memorial day here is the full source:
http://svn.sourceforge.net/viewcvs....ncodingDefinition/gdcmElement.h?view=annotate
Comments welcome.
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.

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

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
 
M

mathieu

Roland said:
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).

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
 
T

Tomás

mathieu posted:

Therefore the standard does not say anything for an array, I can only
change the very first data member:

struct Monkey {
int array[10];
};


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
 
L

Luke Meyers

mathieu said:
If you have nothing to do for memorial day here is the full source:
http://svn.sourceforge.net/viewcvs....ncodingDefinition/gdcmElement.h?view=annotate
Comments welcome.

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.
I simply need to fill in my structure at run time.

You mean like a constructor does?
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.

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?
It's always the same problem interfacing templated code with run time
information.

There are definitely complexities involved. I'm confused, though,
because your question had nothing to do with templates.
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 :)

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
 
M

mathieu

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

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top