Casting struct to char array (was: Linked List problem)

A

Alex Vinokur

Richard Bos said:
(e-mail address removed) (Ben) wrote: [snip]
2) Structure casted into an array of char
typedef struct {
char name[20];
int age;
int id;
} person;

person p = (person *) malloc(sizeof(person));
p.name="hello";
p.age=2;
p.id=2;

char *a;
a=(char *)p;

No. You cannot cast a struct into a pointer. And what would you do this
for, anyway? Do you suppose that the bytes represented by "hello"
somehow form a valid pointer?
I suspect you meant to access the struct itself _through_, not _as_, a
pointer to char. In that case, you need to do

a = (char *)&p;

which is perfectly legal, and can be useful - though rarely. Beware the
padding bytes!
[snip]

Is it possible to write 'operator char*()' inside the C++-structure that enables to avoid the padding problem?
 
V

Victor Bazarov

Alex said:
Richard Bos said:
(e-mail address removed) (Ben) wrote:
[snip]
2) Structure casted into an array of char
typedef struct {
char name[20];
int age;
int id;
} person;

person p = (person *) malloc(sizeof(person));
p.name="hello";
p.age=2;
p.id=2;

char *a;
a=(char *)p;

No. You cannot cast a struct into a pointer. And what would you do this
for, anyway? Do you suppose that the bytes represented by "hello"
somehow form a valid pointer?
I suspect you meant to access the struct itself _through_, not _as_, a
pointer to char. In that case, you need to do

a = (char *)&p;

which is perfectly legal, and can be useful - though rarely. Beware the
padding bytes!

[snip]

Is it possible to write 'operator char*()' inside the C++-structure that enables to avoid the padding problem?

Which "padding problem" is it?

V
 
A

Alex Vinokur

Victor Bazarov said:
Alex said:
Richard Bos said:
(e-mail address removed) (Ben) wrote:
[snip]

2) Structure casted into an array of char
typedef struct {
char name[20];
int age;
int id;
} person;

person p = (person *) malloc(sizeof(person));
p.name="hello";
p.age=2;
p.id=2;

char *a;
a=(char *)p;

No. You cannot cast a struct into a pointer. And what would you do this
for, anyway? Do you suppose that the bytes represented by "hello"
somehow form a valid pointer?
I suspect you meant to access the struct itself _through_, not _as_, a
pointer to char. In that case, you need to do

a = (char *)&p;

which is perfectly legal, and can be useful - though rarely. Beware the
padding bytes!

[snip]

Is it possible to write 'operator char*()' inside the C++-structure that enables to avoid the padding problem?

Which "padding problem" is it?

V


--------- C++ code : BEGIN ---------
// File foo.cpp
#include <iostream>
using namespace std;

struct Foo1
{
char ch1;
char ch2;
short sh1;
Foo1 () : ch1 ('a'), ch2('b'), sh1 (0x6364) {};

};

struct Foo2
{
char ch1;
short sh1;
char ch2;
Foo2 () : ch1 ('a'), sh1 (0x6364), ch2('b') {};

};


#define SHOW(x,i) cout << #x << "[" << i << "] = " << x << endl

int main ()
{
Foo1 foo1;
Foo2 foo2;
char* charray1 = (char*)&foo1;
char* charray2 = (char*)&foo2;

cout << "Foo1" << endl;
SHOW (charray1, 0);
SHOW (charray1, 1);
SHOW (charray1, 2);
SHOW (charray1, 3);

cout << endl;
cout << "Foo2" << endl;
SHOW (charray2, 0);
SHOW (charray2, 1);
SHOW (charray2, 2);
SHOW (charray2, 3);
SHOW (charray2, 4);

return 0;
}
--------- C++ code : END -----------



--------- Compilation & Run : BEGIN ---------

$ g++ -v
[omitted]
gcc version 3.3.3 (cygwin special)


$ g++ -W -Wall foo.cpp
// No errors/warnings

$ a

Foo1
charray1[0] = a
charray1[1] = b
charray1[2] = d
charray1[3] = c

Foo2
charray2[0] = a
charray2[1] = ~
charray2[2] = d
charray2[3] = c
charray2[4] = b

--------- Compilation & Run : END -----------

We can see that ch2 from Foo1 and Foo2 is in the different places of charray1 and charray2
because charray2[1] is a hole.
 
V

Victor Bazarov

Alex said:
Victor Bazarov said:
Alex said:
(e-mail address removed) (Ben) wrote:

[snip]


2) Structure casted into an array of char
typedef struct {
char name[20];
int age;
int id;
} person;

person p = (person *) malloc(sizeof(person));
p.name="hello";
p.age=2;
p.id=2;

char *a;
a=(char *)p;

No. You cannot cast a struct into a pointer. And what would you do this
for, anyway? Do you suppose that the bytes represented by "hello"
somehow form a valid pointer?
I suspect you meant to access the struct itself _through_, not _as_, a
pointer to char. In that case, you need to do

a = (char *)&p;

which is perfectly legal, and can be useful - though rarely. Beware the
padding bytes!


[snip]

Is it possible to write 'operator char*()' inside the C++-structure that enables to avoid the padding problem?

Which "padding problem" is it?

V



--------- C++ code : BEGIN ---------
// File foo.cpp
#include <iostream>
using namespace std;

struct Foo1
{
char ch1;
char ch2;
short sh1;
Foo1 () : ch1 ('a'), ch2('b'), sh1 (0x6364) {};

};

struct Foo2
{
char ch1;
short sh1;
char ch2;
Foo2 () : ch1 ('a'), sh1 (0x6364), ch2('b') {};

};

[...]

--------- Compilation & Run : END -----------

We can see that ch2 from Foo1 and Foo2 is in the different places of charray1 and charray2
because charray2[1] is a hole.

OK, I'll bite. How is that a problem? If your struct is a POD, you may
use 'offsetof' to figure out where exactly a member is, but if it's not
POD, what use do you have for the "position"?

V
 
A

Alex Vinokur

Victor Bazarov said:
Alex said:
Victor Bazarov said:
Alex Vinokur wrote:



(e-mail address removed) (Ben) wrote:

[snip]


2) Structure casted into an array of char
typedef struct {
char name[20];
int age;
int id;
} person;

person p = (person *) malloc(sizeof(person));
p.name="hello";
p.age=2;
p.id=2;

char *a;
a=(char *)p;

No. You cannot cast a struct into a pointer. And what would you do this
for, anyway? Do you suppose that the bytes represented by "hello"
somehow form a valid pointer?
I suspect you meant to access the struct itself _through_, not _as_, a
pointer to char. In that case, you need to do

a = (char *)&p;

which is perfectly legal, and can be useful - though rarely. Beware the
padding bytes!


[snip]

Is it possible to write 'operator char*()' inside the C++-structure that enables to avoid the padding problem?

Which "padding problem" is it?

V



--------- C++ code : BEGIN ---------
// File foo.cpp
#include <iostream>
using namespace std;

struct Foo1
{
char ch1;
char ch2;
short sh1;
Foo1 () : ch1 ('a'), ch2('b'), sh1 (0x6364) {};

};

struct Foo2
{
char ch1;
short sh1;
char ch2;
Foo2 () : ch1 ('a'), sh1 (0x6364), ch2('b') {};

};

[...]

--------- Compilation & Run : END -----------

We can see that ch2 from Foo1 and Foo2 is in the different places of charray1 and charray2
because charray2[1] is a hole.

OK, I'll bite. How is that a problem? If your struct is a POD, you may
use 'offsetof' to figure out where exactly a member is, but if it's not
POD, what use do you have for the "position"?

V

Something like ?


--------- C++ code : BEGIN ---------

#include <iostream>
#include <cassert>
using namespace std;

struct Foo
{
char ch1;
short sh;

char ch2;
char cstr[3];

char ch3;

Foo () : ch1 ('a'), sh (0x6667), ch2('b'), ch3('c') { strcpy (cstr, "de");};

operator char *()
{
const int pure_size (sizeof(ch1) + sizeof(sh) + sizeof(ch2) + strlen(cstr) + sizeof(ch3) + 1);
char* ret_ptr = new char [pure_size];

int i = 0;
ret_ptr[i++] = ch1;

char* tmp_ptr = (char*)&sh;
for (int j = 0; j < sizeof(sh); j++) ret_ptr[i++] = *tmp_ptr++;
ret_ptr[i++] = ch2;

for (int j = 0; j < strlen(cstr); j++) ret_ptr[i++] = cstr[j];

ret_ptr[i++] = ch3;
ret_ptr = 0;
assert (i < pure_size);

return ret_ptr;

};

};


#define SHOW(x,i) cout << #x << "[" << i << "] : ch = " << x << "; hex = " << hex << uint (x) << endl

int main ()
{
Foo foo;
char* charray1 = (char*)&foo;
char* charray2 = (char*)foo;

cout << "Regular (char*)" << endl;
for (int i = 0; i < sizeof (foo); i++) SHOW (charray1, i);

cout << endl;
cout << "Overloaded (char*)" << endl;
for (int i = 0; i < sizeof (foo); i++) SHOW (charray2, i);

return 0;
}

--------- C++ code : END -----------



--------- Compilation & Run : BEGIN ---------

$ g++ -v
[omitted]
gcc version 3.3.3 (cygwin special)


$ g++ foo.cpp
// No errors/warnings

$ a

Regular (char*)
charray1[0] : ch = a; hex = 61
charray1[1] : ch = ; hex = 3
charray1[2] : ch = g; hex = 67
charray1[3] : ch = f; hex = 66
charray1[4] : ch = b; hex = 62
charray1[5] : ch = d; hex = 64
charray1[6] : ch = e; hex = 65
charray1[7] : ch = ; hex = 0
charray1[8] : ch = c; hex = 63
charray1[9] : ch = ð; hex = fffffff0

Overloaded (char*)
charray2[0] : ch = a; hex = 61
charray2[1] : ch = g; hex = 67
charray2[2] : ch = f; hex = 66
charray2[3] : ch = b; hex = 62
charray2[4] : ch = d; hex = 64
charray2[5] : ch = e; hex = 65
charray2[6] : ch = c; hex = 63
charray2[7] : ch = ; hex = 0
charray2[8] : ch = ; hex = 0
charray2[9] : ch = ; hex = 0

--------- Compilation & Run : END -----------
 
A

Alex Vinokur

[snip]
-----------------------
For not POD
Something like ?
-----------------------
[snip]


For POD

--------- C++ code : BEGIN ---------
#include <iostream>
#include <cassert>
using namespace std;

struct Foo
{
char ch1;
short sh;

char ch2;
char cstr[3];

char ch3;

};

char* get_as_cstr(const Foo& foo_i)
{
const int pure_size (sizeof(foo_i.ch1) + sizeof(foo_i.sh) + sizeof(foo_i.ch2) + strlen(foo_i.cstr) + sizeof(foo_i.ch3) + 1);
char* ret_ptr = new char [pure_size];

int i = 0;
ret_ptr[i++] = foo_i.ch1;

char* tmp_ptr = (char*)&foo_i.sh;
for (int j = 0; j < sizeof(foo_i.sh); j++) ret_ptr[i++] = *tmp_ptr++;
ret_ptr[i++] = foo_i.ch2;

for (int j = 0; j < strlen(foo_i.cstr); j++) ret_ptr[i++] = foo_i.cstr[j];

ret_ptr[i++] = foo_i.ch3;
ret_ptr = 0;
assert (i < pure_size);

return ret_ptr;
}


#define SHOW(x,i) cout << #x << "[" << i << "] : ch = " << x << "; hex = " << hex << uint (x) << endl

int main ()
{
Foo foo;
foo.ch1 = 'a';
foo.sh = 0x6667;
foo.ch2 = 'b';
strcpy (foo.cstr, "de");
foo.ch3 = 'c';

char* charray1 = (char*)&foo;
char* charray2 = get_as_cstr (foo);

cout << "POD : Regular (char*)" << endl;
for (int i = 0; i < sizeof (foo); i++) SHOW (charray1, i);

cout << endl;
cout << "POD : Function get_as_cstr" << endl;
for (int i = 0; i < sizeof (foo); i++) SHOW (charray2, i);

return 0;
}


--------- C++ code : END -----------



--------- Compilation & Run : BEGIN ---------

$ g++ -v
[omitted]
gcc version 3.3.3 (cygwin special)


$ g++ foo.cpp
// No errors/warnings

$ a

POD : Regular (char*)
charray1[0] : ch = a; hex = 61
charray1[1] : ch = ; hex = 3
charray1[2] : ch = g; hex = 67
charray1[3] : ch = f; hex = 66
charray1[4] : ch = b; hex = 62
charray1[5] : ch = d; hex = 64
charray1[6] : ch = e; hex = 65
charray1[7] : ch = ; hex = 0
charray1[8] : ch = c; hex = 63
charray1[9] : ch = ð; hex = fffffff0

POD : Function get_as_cstr
charray2[0] : ch = a; hex = 61
charray2[1] : ch = g; hex = 67
charray2[2] : ch = f; hex = 66
charray2[3] : ch = b; hex = 62
charray2[4] : ch = d; hex = 64
charray2[5] : ch = e; hex = 65
charray2[6] : ch = c; hex = 63
charray2[7] : ch = ; hex = 0
charray2[8] : ch = ; hex = 0
charray2[9] : ch = ; hex = 0

--------- Compilation & Run : END -----------
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top