473,657 Members | 2,524 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Distance between struct members

1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?

2. s1 and s2 are type of the same struct S. Can the distance of s1.i4
between i3 be used to deduce the distance between s2.i4 and s2.i3?

Thank you for your time.
#include <stdio.h>
#include <stddef.h>

struct S {
/*...*/
int i3;
/*...*/
int i4;
};

int main(void)
{
struct S s1, s2;
ptrdiff_t distance;

distance = &s1.i4 - &s1.i3;
s1.i3 = 11;
s1.i4 = 12;
s2.i3 = 13;
s2.i4 = 14;
printf("%d, %d\n", s2.i3, *(&s2.i3 + distance));
return 0;
}

Oct 18 '07 #1
18 2173
lovecreatesbea. ..@gmail.com wrote On 10/18/07 12:47,:
1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?
Yes. To see why (or one reason why, anyhow), remember
that pointer arithmetic operates in units of the pointed-to
type. Now consider what might lie in the /*...*/ between
members i3 and i4. If the size of what's there is not an
exact multiple of the size of an int, i3 and i4 are separated
by something-and-a-fraction units. Pointer arithmetic can't
handle the -and-a-fraction part.
2. s1 and s2 are type of the same struct S. Can the distance of s1.i4
between i3 be used to deduce the distance between s2.i4 and s2.i3?
Yes, but let's tighten up what "distance" means. If
you express everything in units of bytes (rather than ints
or whatever), all will be well. C guarantees that

(char*)&s1.i4 - (char*)&s1.i3
== (char*)&s2.i4 - (char*)&s2.i3

However, there are no guarantees about

(char*)&s1.i3 - (char*)s2.i3

Thank you for your time.
#include <stdio.h>
#include <stddef.h>

struct S {
/*...*/
int i3;
/*...*/
int i4;
};

int main(void)
{
struct S s1, s2;
ptrdiff_t distance;

distance = &s1.i4 - &s1.i3;
s1.i3 = 11;
s1.i4 = 12;
s2.i3 = 13;
s2.i4 = 14;
printf("%d, %d\n", s2.i3, *(&s2.i3 + distance));
return 0;
}
Oct 18 '07 #2
Eric Sosman <Er*********@su n.comwrites:
lovecreatesbea. ..@gmail.com wrote On 10/18/07 12:47,:
>1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?

Yes. To see why (or one reason why, anyhow), remember
that pointer arithmetic operates in units of the pointed-to
type. Now consider what might lie in the /*...*/ between
members i3 and i4. If the size of what's there is not an
exact multiple of the size of an int, i3 and i4 are separated
by something-and-a-fraction units. Pointer arithmetic can't
handle the -and-a-fraction part.
[...]

Yes, but that's just one reason, and it depends on what you mean by
"illegal".

The real reason is that pointer subtraction invokes undefined behavior
if the two pointers point to distinct objects. See C99 6.5.6p9. This
applies even to subtraction of char* pointers, which are not affected
by alignment.

(In a typical implementation, the subtraction is likely to give you a
somewhat meaningful result. If the the difference is not a multiple
of the size of the pointed-to object, the remainder is likely to be
quitely ignored. But there are, of course, absolutely no guarantees.)

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 18 '07 #3
On Thu, 18 Oct 2007 15:21:21 -0700, Keith Thompson <ks***@mib.or g>
wrote in comp.lang.c:
Eric Sosman <Er*********@su n.comwrites:
lovecreatesbea. ..@gmail.com wrote On 10/18/07 12:47,:
1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?
Yes. To see why (or one reason why, anyhow), remember
that pointer arithmetic operates in units of the pointed-to
type. Now consider what might lie in the /*...*/ between
members i3 and i4. If the size of what's there is not an
exact multiple of the size of an int, i3 and i4 are separated
by something-and-a-fraction units. Pointer arithmetic can't
handle the -and-a-fraction part.
[...]

Yes, but that's just one reason, and it depends on what you mean by
"illegal".

The real reason is that pointer subtraction invokes undefined behavior
if the two pointers point to distinct objects. See C99 6.5.6p9. This
applies even to subtraction of char* pointers, which are not affected
by alignment.
I disagree about using pointer to char, specifically pointer to
unsigned.

Any object, including the structure in the OP's post, can be accessed
as a suitably sized array of unsigned char. It is legal, therefore,
to subtract the addresses of two members of the same structure,
provided of course they are cast to pointers to unsigned char.

The result will be a ptrdiff_t representing the number of bytes
between the first byte in the representation of the first member and
the first byte in the representation of the second member.

I do agree about using pointers to int, regardless of alignment
issues, because clearly two different int members of a structure are
not elements of the same array of ints.
(In a typical implementation, the subtraction is likely to give you a
somewhat meaningful result. If the the difference is not a multiple
of the size of the pointed-to object, the remainder is likely to be
quitely ignored. But there are, of course, absolutely no guarantees.)
Now the question is, can anybody find wording in the standard
(probably scattered abound in multiple places) that definitively makes
doing this with pointer to char or pointer to signed char well-defined
because it is well-defined for pointer to unsigned char?

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Oct 19 '07 #4
Jack Klein <ja*******@spam cop.netwrites:
On Thu, 18 Oct 2007 15:21:21 -0700, Keith Thompson <ks***@mib.or g>
wrote in comp.lang.c:
>Eric Sosman <Er*********@su n.comwrites:
lovecreatesbea. ..@gmail.com wrote On 10/18/07 12:47,:
1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?

Yes. To see why (or one reason why, anyhow), remember
that pointer arithmetic operates in units of the pointed-to
type. Now consider what might lie in the /*...*/ between
members i3 and i4. If the size of what's there is not an
exact multiple of the size of an int, i3 and i4 are separated
by something-and-a-fraction units. Pointer arithmetic can't
handle the -and-a-fraction part.
[...]

Yes, but that's just one reason, and it depends on what you mean by
"illegal".

The real reason is that pointer subtraction invokes undefined behavior
if the two pointers point to distinct objects. See C99 6.5.6p9. This
applies even to subtraction of char* pointers, which are not affected
by alignment.

I disagree about using pointer to char, specifically pointer to
unsigned.

Any object, including the structure in the OP's post, can be accessed
as a suitably sized array of unsigned char. It is legal, therefore,
to subtract the addresses of two members of the same structure,
provided of course they are cast to pointers to unsigned char.
Certainly.

I may have misread your comments above. I thought you were talking
about subtracting pointers to members of distinct objects, rather than
pointers to members of the same object.

Subtracting two char* pointers, if they both point into the same
object (or just past its end) is valid. Subtracting two pointers of
any type that point to distinct objects invokes undefined behavior.
Subtracting two pointers to non-char types, both of which point into
the same structure, probably invokes undefined behavior because of the
alignment issues you mentioned above.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 19 '07 #5
Keith Thompson wrote:
Eric Sosman <Er*********@su n.comwrites:
>lovecreatesbea ...@gmail.com wrote On 10/18/07 12:47,:
>>1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?
Yes. To see why (or one reason why, anyhow), remember
that pointer arithmetic operates in units of the pointed-to
type. Now consider what might lie in the /*...*/ between
members i3 and i4. If the size of what's there is not an
exact multiple of the size of an int, i3 and i4 are separated
by something-and-a-fraction units. Pointer arithmetic can't
handle the -and-a-fraction part.
[...]

Yes, but that's just one reason, and it depends on what you mean by
"illegal".

The real reason is that pointer subtraction invokes undefined behavior
if the two pointers point to distinct objects. See C99 6.5.6p9. This
applies even to subtraction of char* pointers, which are not affected
by alignment.
Well, that's no "reason" at all: It just states the Law
and offers no argument for why the Law should be as it is.
The most famous example of that particular argument is surely
"I am that I am," which few mortals can bring off believably.

In the example you snipped, the subtraction of int* pointers
was not well-defined but the subtraction of char* pointers was.

--
Eric Sosman
es*****@ieee-dot-org.invalid
Oct 19 '07 #6
Eric Sosman <es*****@ieee-dot-org.invalidwrit es:
[...]
In the example you snipped, the subtraction of int* pointers
was not well-defined but the subtraction of char* pointers was.
Yes, because I misread it.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 19 '07 #7
Keith Thompson wrote:
>
Eric Sosman <Er*********@su n.comwrites:
lovecreatesbea. ..@gmail.com wrote On 10/18/07 12:47,:
1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?
Yes. To see why (or one reason why, anyhow), remember
that pointer arithmetic operates in units of the pointed-to
type. Now consider what might lie in the /*...*/ between
members i3 and i4. If the size of what's there is not an
exact multiple of the size of an int, i3 and i4 are separated
by something-and-a-fraction units. Pointer arithmetic can't
handle the -and-a-fraction part.
[...]

Yes, but that's just one reason, and it depends on what you mean by
"illegal".

The real reason is that pointer subtraction invokes undefined behavior
if the two pointers point to distinct objects. See C99 6.5.6p9. This
applies even to subtraction of char* pointers, which are not affected
by alignment.
But &s1.i4 and &s1.i3 are both pointers within s1, and therefore are
not "distinct objects". (I suppose the typical "IMO" disclaimer may
apply?)

Plus, as I understand it, it is perfectly legal to overlay an array
of unsigned chars on any object, and access any and all bytes within
that object through this array. How is casting &s1.i4 and &s1.i3 to
"unsigned char *" any different than overlaying an unsigned char
array?

On second thought, however, I can see that taking the addresses of
the two as their native "int *", you can say that the two ints are
not part of the same object, as they are not part of an array of
ints. (Which is why they may not be a multiple-of-sizeof-int bytes
apart.) It is the casting to "unsigned char *" which means that the
addresses can be treated "as-if" they were part of an array of
unsigned chars the size of the struct.

Perhaps we're both right?
(In a typical implementation, the subtraction is likely to give you a
somewhat meaningful result. If the the difference is not a multiple
of the size of the pointed-to object, the remainder is likely to be
quitely ignored. But there are, of course, absolutely no guarantees.)
I think offsetof() is the way to go here. The offset of s1.i3 is
guaranteed to be the same as the offset of s2.i3, assuming that s1
and s2 are the same type, and any arithmetic which arrives at that
offset is guaranteed to be properly aligned.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer .h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th***** ********@gmail. com>
Oct 19 '07 #8
On Oct 19, 1:46 am, Eric Sosman <Eric.Sos...@su n.comwrote:
lovecreatesbea. ..@gmail.com wrote On 10/18/07 12:47,:
1. The following code snippet uses minus operation on two pointers to
calculate the distance between struct members. This is illegal, right?

Yes. To see why (or one reason why, anyhow), remember
that pointer arithmetic operates in units of the pointed-to
type. Now consider what might lie in the /*...*/ between
members i3 and i4. If the size of what's there is not an
exact multiple of the size of an int, i3 and i4 are separated
by something-and-a-fraction units. Pointer arithmetic can't
handle the -and-a-fraction part.
2. s1 and s2 are type of the same struct S. Can the distance of s1.i4
between i3 be used to deduce the distance between s2.i4 and s2.i3?

Yes, but let's tighten up what "distance" means. If
you express everything in units of bytes (rather than ints
or whatever), all will be well. C guarantees that

(char*)&s1.i4 - (char*)&s1.i3
== (char*)&s2.i4 - (char*)&s2.i3

However, there are no guarantees about

(char*)&s1.i3 - (char*)s2.i3
Thank you.

So, the extra casts make the code in the original post legal and
portable, doesn't it?

#include <stdio.h>
#include <stddef.h>

struct S {
/*...*/
int i3;
/*...*/
int i7;
};

int main(void)
{
struct S s1 = {11, 12}, s2 = {13, 14};
ptrdiff_t distance;

distance = (char *)&s1.i7 - (char *)&s1.i3;
printf("%d, %d\n", s2.i3, (int)*((char *)&s2.i3 + distance));
return 0;
}

Thank you for your time.
#include <stdio.h>
#include <stddef.h>
struct S {
/*...*/
int i3;
/*...*/
int i4;
};
int main(void)
{
struct S s1, s2;
ptrdiff_t distance;
distance = &s1.i4 - &s1.i3;
s1.i3 = 11;
s1.i4 = 12;
s2.i3 = 13;
s2.i4 = 14;
printf("%d, %d\n", s2.i3, *(&s2.i3 + distance));
return 0;
}- Hide quoted text -

- Show quoted text -
Oct 19 '07 #9
On Oct 19, 10:28 pm, Kenneth Brody <kenbr...@spamc op.netwrote:
I think offsetof() is the way to go here. The offset of s1.i3 is
guaranteed to be the same as the offset of s2.i3, assuming that s1
and s2 are the same type, and any arithmetic which arrives at that
offset is guaranteed to be properly aligned.
But the offsetof() uses size_t other than "char *" or "unsigned char
*" to designate the type of the addresses, why?

Oct 19 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
31571
by: Steve | last post by:
I'll be the first to admit, I'm not entirely clear on the appropriate usage of either. From what I am reading in my books, a Struct and a Class are pretty much the same, with the difference being, a Class can have private and protected members, but a Struct everything is Public by default. I laymans terms what would be an appropriate reason to choose a Struct over a Class? So why would one want to choose a Class over a Struct.
19
1814
by: Yoon Soo | last post by:
Hi, there while mixing assembler and c code I got the following question: struct bar { int bar_val1; int bar_val2; (...) }
21
2464
by: hermes_917 | last post by:
I want to use memcpy to copy the contents of one struct to another which is a superset of the original struct (the second struct has extra members at the end). I wrote a small program to test this, and it seems to work fine, but are there any cases where doing something like this could cause any problems? Here's the small program I wrote to test this: #include <stdio.h>
7
1871
by: Urs Wigger | last post by:
In a C++ project, I have the following struct definition: struct GridModeDataT { double dVal1; double dVal2; double dVal3; long lNumberOfPoints; int bUseRegion; enum ES_RegionType regionType;
5
8726
by: Chris | last post by:
Hi, I don't get the difference between a struct and a class ! ok, I know that a struct is a value type, the other a reference type, I understand the technical differences between both, but conceptually speaking : when do I define something as 'struct' and when as 'class' ? for example : if I want to represent a 'Time' thing, containing : - data members : hours, mins, secs
19
7528
by: John | last post by:
In STL's map implementation, the distance between two iterators it1, it2 takes O(K) to compute where K is the actual distance between the two iterators. In theory, a red black tree can do this in O(log K) time. Anyone knows if there is a way to do this in map<> or if map<> can be inherited/modified to do this? Thanks, --j
5
3323
by: Bill Pursell | last post by:
Suppose I have a structure with many members, and I pass a pointer to that structure to a function. I'd like the prototype of the function to specify that it will only be changing certain members of the function, but I have only the following horrific way to do that. Can someone please suggest a better alternative? #include <stdio.h> struct foo { char *a;
4
2583
by: Michael Brennan | last post by:
I have a menu_item structure containing an union. func is used if the menu item should use a callback, and submenu if a popupmen should be shown. struct menu_item { enum { function, popup } type; union { int (*func)(int); struct menu_item *submenu; } action;
12
5523
by: Milux | last post by:
Hi All, This question has to do with interface design. Suppose I have an translation tool. It can translates structs from type "general" to other types and then does some processing. Example: typedef struct {
0
8411
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8739
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8513
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
6176
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5638
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4173
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4329
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2740
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1969
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.