424,066 Members | 2,120 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,066 IT Pros & Developers. It's quick & easy.

Type Casting IPv4 and IPv6 structures to Generic Structures

P: n/a
I'm struggling with the concept of typecasting when
setting up a TCP client.

Here's a code snip (modified from W. Richard Stevens Unix Programming
book) to demonstrate where I am struggling:

int sockfd;
struct sockaddr_in servaddr;

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13); /* PORT 13 */

/* argv[1] = "127.0.0.1" */

if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr)) <= 0 ) {
perror("inet_pton()");
exit(1);
}

if ( (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) <
0) {
perror("connect()");
exit(1);
}

When this line occurs:

(struct sockaddr *) &servaddr

the previously assigned values within servaddr are typecast to struct
sockaddr,
which is defined as:

struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

My confusion is how sa_data[14] becomes populated. I do not
understand the conversion.

Can anyone help me out?

I stepped through the code creating a pointer of type struct sockaddr
and pointed it to the address of servaddr. But I do not understand
why sa_data[14] would have data looking like \111\0\r\0\0 . . .
nor do I understand how to convert that string back to it's original
form.

Any help would be appreciated.

Thanks,

Brian

P.S. I'm compiling using gcc, and debuggin with gdb.
Nov 14 '05 #1
Share this Question
Share on Google+
14 Replies


P: n/a
tweak wrote:
I'm struggling with the concept of typecasting when setting
up a TCP client.

Here's a code snip (modified from W. Richard Stevens Unix
Programming book) to demonstrate where I am struggling:


Try comp.unix.programmer or (perhaps) comp.os.linux.development.apps

Nov 14 '05 #2

P: n/a
I do not see why typecasting structures would be specific to unix.
You should be able to do this across platforms. I am posting here
to find out about the conversion between the two structures. I
do not understand the integer to char[] type conversion happening
when I write:

(struct sockaddr *) &servaddr

I can setup a pointer of type struct sockaddr and see in gdb
the conversion. I just don't understand it.

Here's some code to do that;

struct sockaddr *test;

test = (struct sockaddr *) &servaddr

the above just passes the address to the pointer test.

Now in gdb, I can do a display of *test and see what's
in the structure. But I do not understand the char[]
conversion.

Thanks,

Brian

P.S. I posted this thread again under a different name, hoping
to get general C answers about the conversion without scaring
away folks that haven't messed with socket programming.
Grumble wrote:
tweak wrote:
I'm struggling with the concept of typecasting when setting
up a TCP client.

Here's a code snip (modified from W. Richard Stevens Unix
Programming book) to demonstrate where I am struggling:

Try comp.unix.programmer or (perhaps) comp.os.linux.development.apps

Nov 14 '05 #3

P: n/a
"tweak" <bw********@cox.net> wrote in message
news:us_xc.30344$My6.19961@fed1read05...
I do not see why typecasting structures would be specific to unix.
You should be able to do this across platforms. I am posting here
to find out about the conversion between the two structures. I
do not understand the integer to char[] type conversion happening
when I write:
To avoid offending some here, you should simplify your question to the
minimal code needed, including all the type definitions that are not part of
Standard C, like this:

struct foo {
int a,b,c,d;
int e;
}

struct bar {
int a,b,c,d;
char e[sizeof(int)];
}

Now, if I understand correctly, your question is what happens when you cast
a (struct foo *) to a (struct bar *).

The short answer is: absolutely nothing at the time of the cast, but
accessing the 'e' member (of the casted form) invokes implementation-defined
behavior. (I think)
Now in gdb, I can do a display of *test and see what's
in the structure. But I do not understand the char[]
conversion.


There is no conversion. In the particular case you cite, there are many
variants of struct sockaddr each with unique contents; the char[] at the end
is padding such that all of the structs have the same size. This allows one
to pass a (struct sockaddr_in *) to a function expecting a (struct sockaddr
*), provided you also pass an idenfier, i.e. AF_INET, which tells the
receiving function how to properly cast the argument back to extract its
contents.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

Nov 14 '05 #4

P: n/a
On Wed, 09 Jun 2004 23:18:43 -0700, tweak <bw*******@cox.net> wrote:
(struct sockaddr *) &servaddr

the previously assigned values within servaddr are typecast to struct
sockaddr,
which is defined as:

struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

My confusion is how sa_data[14] becomes populated. I do not
understand the conversion.


It's not really a conversion. Nothing is moved or changed. You are
just pretending that block of storage is now a struct sockaddr, where
before you were pretending it was a struct sockaddr_in. Whatever was
in those storage locations is still there.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #5

P: n/a
In <c3******************************@news.teranews.co m> "Stephen Sprunk" <st*****@sprunk.org> writes:
"tweak" <bw********@cox.net> wrote in message
news:us_xc.30344$My6.19961@fed1read05...
I do not see why typecasting structures would be specific to unix.
You should be able to do this across platforms. I am posting here
to find out about the conversion between the two structures. I
do not understand the integer to char[] type conversion happening
when I write:
To avoid offending some here, you should simplify your question to the
minimal code needed, including all the type definitions that are not part of
Standard C, like this:

struct foo {
int a,b,c,d;
int e;
}

struct bar {
int a,b,c,d;
char e[sizeof(int)];
}

Now, if I understand correctly, your question is what happens when you cast
a (struct foo *) to a (struct bar *).

The short answer is: absolutely nothing at the time of the cast, but


This is not neccesarily correct. Casts between different types mean
conversions and there is nothing in the C standard telling us that
pointers to different structures use the same representation.
What is true is that the pointed-to object is not affected in any
way by the cast.
accessing the 'e' member (of the casted form) invokes implementation-defined
behavior. (I think)


It depends on how you access it. Barring a pathological implementation
that inserts arbitrary padding, if you treat the array e as containing
an int, everything is fine. If you look at it on a byte by byte basis,
then it's better to declare it as array of unsigned char. In that case,
you can access the representation of the corresponding field of struct
foo.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #6

P: n/a
In <oc********************************@4ax.com> Alan Balmer <al******@att.net> writes:
On Wed, 09 Jun 2004 23:18:43 -0700, tweak <bw*******@cox.net> wrote:
(struct sockaddr *) &servaddr

the previously assigned values within servaddr are typecast to struct
sockaddr,
which is defined as:

struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

My confusion is how sa_data[14] becomes populated. I do not
understand the conversion.


It's not really a conversion. Nothing is moved or changed.


Except for the pointer value itself, that is *converted* from one type to
another. If you claim that this conversion is a no-op, please provide
chapter and verse.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #7

P: n/a
>On Wed, 09 Jun 2004 23:18:43 -0700, tweak <bw*******@cox.net> wrote:
(struct sockaddr *) &servaddr
... the previously assigned values within servaddr are typecast to
struct sockaddr ...

In article <news:oc********************************@4ax.com >
Alan Balmer <al******@spamcop.net> writes:It's not really a conversion. Nothing is moved or changed.
Well, more precisely, there *is* a conversion -- but the conversion
is not the one quoted in ">>" above.
You are just pretending that block of storage is now a struct
sockaddr, where before you were pretending it was a struct
sockaddr_in. Whatever was in those storage locations is still there.


This, of course, is correct.

The result of "&servaddr" -- a value of type "pointer to struct A"
(for some A) -- is converted to a new value of type "pointer to
struct B" (for some B). The data to which the original pointer
points are unchanged, but whether the new pointer is at all useful
is specific to the implementation.

Unix-like systems with "sockaddr"s and "sockaddr_in"s -- let me
call these "POSIX systems" for short, although even that is not
strictly true -- are much more strongly constrained than is "C in
general", so that while much of POSIX can be written using C, there
are machines that can run C that can never run POSIX. This is
similar to the way that all trucks are vehicles, but not all vehicles
are trucks. If you specify "a vehicle that can carry three tons
of cargo", you have ruled out a lot of possible vehicles -- but
now you can be sure that you can do something with the remaining
subset. (If you load three tons of cargo onto a Yugo or a racecar,
what happens?) If you specify "a computer that has POSIX", you have
ruled out a lot of possible computers, but now you can be sure you
can do something -- sockaddr and sockaddr_in, for instance -- with
the remaining subset.

Here in comp.lang.c we try not to get too specific about large-scale
cargo-hauling, in case your interests are Formula 1 racers or
restoring Model Ts. :-) We try to talk about things that apply
to *all* C systems, as defined by the C standard.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #8

P: n/a
On 10 Jun 2004 16:12:44 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <oc********************************@4ax.com> Alan Balmer <al******@att.net> writes:
On Wed, 09 Jun 2004 23:18:43 -0700, tweak <bw*******@cox.net> wrote:
(struct sockaddr *) &servaddr

the previously assigned values within servaddr are typecast to struct
sockaddr,
which is defined as:

struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

My confusion is how sa_data[14] becomes populated. I do not
understand the conversion.


It's not really a conversion. Nothing is moved or changed.


Except for the pointer value itself, that is *converted* from one type to
another. If you claim that this conversion is a no-op, please provide
chapter and verse.

He didn't ask about the pointer value, but the contents of the struct.

Go away.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #9

P: n/a
Dan Pop wrote:
In <c3******************************@news.teranews.co m> "Stephen Sprunk" <st*****@sprunk.org> writes:

"tweak" <bw********@cox.net> wrote in message
news:us_xc.30344$My6.19961@fed1read05...
I do not see why typecasting structures would be specific to unix.
You should be able to do this across platforms. I am posting here
to find out about the conversion between the two structures. I
do not understand the integer to char[] type conversion happening
when I write:


To avoid offending some here, you should simplify your question to the
minimal code needed, including all the type definitions that are not part of
Standard C, like this:

struct foo {
int a,b,c,d;
int e;
}

struct bar {
int a,b,c,d;
char e[sizeof(int)];
}

Now, if I understand correctly, your question is what happens when you cast
a (struct foo *) to a (struct bar *).

The short answer is: absolutely nothing at the time of the cast, but

This is not neccesarily correct. Casts between different types mean
conversions and there is nothing in the C standard telling us that
pointers to different structures use the same representation.
What is true is that the pointed-to object is not affected in any
way by the cast.

accessing the 'e' member (of the casted form) invokes implementation-defined
behavior. (I think)

It depends on how you access it. Barring a pathological implementation
that inserts arbitrary padding, if you treat the array e as containing
an int, everything is fine. If you look at it on a byte by byte basis,
then it's better to declare it as array of unsigned char. In that case,
you can access the representation of the corresponding field of struct
foo.

Dan


I will now modify my code going forward to simple examples.

Cheers,

Brian
Nov 14 '05 #10

P: n/a
Alan Balmer wrote:
On Wed, 09 Jun 2004 23:18:43 -0700, tweak <bw*******@cox.net> wrote:

(struct sockaddr *) &servaddr

the previously assigned values within servaddr are typecast to struct
sockaddr,
which is defined as:

struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

My confusion is how sa_data[14] becomes populated. I do not
understand the conversion.

It's not really a conversion. Nothing is moved or changed. You are
just pretending that block of storage is now a struct sockaddr, where
before you were pretending it was a struct sockaddr_in. Whatever was
in those storage locations is still there.


If you assign the cast portion of the function to a pointer of the
typecast and dereference that pointer, the values appear to change.
I will say that convert to something, but don't actually change.

/* create pointer of type cast */

struct sockaddr *test;

/* assign servaddr */

test = (struct sockaddr *) &servaddr

in gdb, look at *test after the assignment.

sa_data looks like "\0\117\r\0 . . . "

I put the actual output in my response to my typecasting
structures thread.

I do not understand sa_data[]. I understand that the last
zeros exist to establish the structure at a specific size,
but I do not understand the items before the '\0' padding.

Any ideas?

Cheers,

Brian
Nov 14 '05 #11

P: n/a
On 10 Jun 2004 16:12:44 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <oc********************************@4ax.com> Alan Balmer <al******@att.net> writes:
On Wed, 09 Jun 2004 23:18:43 -0700, tweak <bw*******@cox.net> wrote:
(struct sockaddr *) &servaddr

the previously assigned values within servaddr are typecast to struct
sockaddr,
which is defined as:

struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

My confusion is how sa_data[14] becomes populated. I do not
understand the conversion.


It's not really a conversion. Nothing is moved or changed.


Except for the pointer value itself, that is *converted* from one type to
another. If you claim that this conversion is a no-op, please provide
chapter and verse.


The requirement that all pointers to struct have the same
representation would seem to satisfy your request.
<<Remove the del for email>>
Nov 14 '05 #12

P: n/a
"Dan Pop" <Da*****@cern.ch> wrote:
"Stephen Sprunk" <st*****@sprunk.org> wrote:
Now, if I understand correctly, your question is what happens
when you cast a (struct foo *) to a (struct bar *).

The short answer is: absolutely nothing at the time of the
cast, but


This is not neccesarily correct. Casts between different types
mean conversions and there is nothing in the C standard telling
us that pointers to different structures use the same
representation. What is true is that the pointed-to object is
not affected in any way by the cast.


C99 6.6.2.1 #26 "All pointers to structure types shall have the same
representation and alignment requirements as each other."

The type of the expression changes, but the representation of the pointer
value does not.

--
Simon.
Nov 14 '05 #13

P: n/a
Barry Schwarz wrote:
On 10 Jun 2004 16:12:44 GMT, Da*****@cern.ch (Dan Pop) wrote:

.... snip ...

Except for the pointer value itself, that is *converted* from
one type to another. If you claim that this conversion is a
no-op, please provide chapter and verse.


The requirement that all pointers to struct have the same
representation would seem to satisfy your request.


Meaning they fit in the same space. However they obviously need
not have the same value, which is some collection of bits. I see
no prohibition against some variation in some of those bits in
accordance with the actual type. I also see no reason for any
implementation to do so.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #14

P: n/a
Dan Pop wrote:
In <oc********************************@4ax.com> Alan Balmer <al******@att.net> writes:

On Wed, 09 Jun 2004 23:18:43 -0700, tweak <bw*******@cox.net> wrote:

(struct sockaddr *) &servaddr

the previously assigned values within servaddr are typecast to struct
sockaddr,
which is defined as:

struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

My confusion is how sa_data[14] becomes populated. I do not
understand the conversion.


It's not really a conversion. Nothing is moved or changed.

Except for the pointer value itself, that is *converted* from one type to
another. If you claim that this conversion is a no-op, please provide
chapter and verse.


ISO/IEC 9899:1999, section 6.2.5, paragraph 26, third sentence.

--
Er*********@sun.com

Nov 14 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.