473,396 Members | 1,826 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Type Casting IPv4 and IPv6 structures to Generic Structures

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
14 2963
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
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
"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
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
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
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
>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 (40°39.22'N, 111°50.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
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
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
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
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
"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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Arnaud Legrand | last post by:
Hello, I have a question about portability and I have not found the answer in the FAQ. I have different modules to build. All of them have the same private part and a common public part (though...
10
by: Bob | last post by:
This has been bugging me for a while now. GetType isn't availble for variables decalred as interface types, I have to DirectCast(somevariable, Object). In example: Sub SomeSub(ByVal...
6
by: Charles Law | last post by:
I want to do something like this: obj = CType(value, Value.Type) Well, not exactly, but I think that captures the essence. I realise it won't work as I have written it, and it looks a bit like...
8
by: Kris Jennings | last post by:
Hi, I am trying to create a new generic class and am having trouble casting a generic type to a specific type. For example, public class MyClass<Twhere T : MyItemClass, new() { public...
59
by: peter.tornqvist | last post by:
Maybe I'm stupid or maybe I am missing the obvious, but I can't find a way to define a type alias in C# for primitive types (class and interfaces I can inherit from, no problem). I.e I want to...
2
by: Valerie Hough | last post by:
My app has so far only encountered IPv4 addresses and I use: Dns.GetHostByName( "someOtherComputer", portNumber ).AddressList. Can someone please point me to an example of how to turn this into...
1
by: =?Utf-8?B?V2lsbGlhbSBSYW5kbGV0dA==?= | last post by:
The System.Uri class is not behaving as I expect when an IPv4 address is embedded within an IPv6 address. The following test works fine, using IPv6 only: public void...
14
by: Simon | last post by:
Hi, is there a straight forward way of converting IPv4 to IPv6? I thought that it was just a matter of converting 32 bits to 128 bits, (by adding 96 leading 0s), but that does not seem right...
5
by: Chad | last post by:
Keith made the following comment " You can convert an int*, or an int**, or an int***, or ... to void* without loss of information -- except that you lose the type information, which you have to...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.