473,399 Members | 4,177 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,399 software developers and data experts.

portable code

Hi,
I recently came across a piece of code like this,
( & ( ( ( some struct * ) 0 ) -> element ) ) )

I had never seen this kind of code being used in any implementations so
far, but somehow remembered to have seen it sometime in clc, and that it
was for finding the offset of a member in a structure ( if I am not
horribly mistaken).

Now does this work ? Does this actually use the address 0x0, and when we
cast it to the particular structure, and try to obtain the address of an
element through this pointer, which turns out to be the offset of the
member because the base address is 0x0.

Many of you might argue about portability,but I have seen this code work
on multiple platforms.This means, it does work for quite a few different
platforms ( obviously with different implementations ), though it might
fail on some weird platform.Can we safely use this non-standard code in
places where we would have used a offsetof ?

Thanx,
~
Nov 14 '05 #1
5 1543
grid <pr******@gmail.com> writes:
I recently came across a piece of code like this,
( & ( ( ( some struct * ) 0 ) -> element ) ) )

I had never seen this kind of code being used in any implementations
so far, but somehow remembered to have seen it sometime in clc, and
that it was for finding the offset of a member in a structure ( if I
am not horribly mistaken).

Now does this work ? Does this actually use the address 0x0, and when
we cast it to the particular structure, and try to obtain the address
of an element through this pointer, which turns out to be the offset
of the member because the base address is 0x0.
No. The result of the expression you quote is a pointer. To get an
offset, you need to subtract (some struct *)0. The resulting value is
the difference between two pointers, so the actual value of the base
pointer does not matter:

#define offsetof(type, field) ((size_t)((char *)&((type *)0)->field - (char *)(type *)0))

You need the (char *) casts because &((type *)0)->field and (type *)0
are pointers to objects of incompatible types, so you can't subtract
one from the other directly.
Many of you might argue about portability,but I have seen this code
work on multiple platforms.This means, it does work for quite a few
different platforms ( obviously with different implementations ),
though it might fail on some weird platform.Can we safely use this
non-standard code in places where we would have used a offsetof ?


This is how offsetof is implemented on many platforms.

DES
--
Dag-Erling Smørgrav - de*@des.no
Nov 14 '05 #2
grid wrote:
...
I recently came across a piece of code like this,
( & ( ( ( some struct * ) 0 ) -> element ) ) )

I had never seen this kind of code being used in any implementations so
far, but somehow remembered to have seen it sometime in clc, and that it
was for finding the offset of a member in a structure ( if I am not
horribly mistaken).
This looks like [a portion of] the popular way to implement the
'offsetof' macro in the standard library.
Now does this work ?
In 'offsetof' it assumes that the resultant value, after conversion to
integral type, will represent the offset of the field in the structure.
Does this actually use the address 0x0, and when we
cast it to the particular structure, and try to obtain the address of an
element through this pointer, which turns out to be the offset of the
member because the base address is 0x0.
Exactly.
Many of you might argue about portability,but I have seen this code work
on multiple platforms.
As a part of standard library implementation, it is perfectly fine. The
implementation of the standard library is not required to be portable.
It is not even required to be implemented in C. It is just required to
work in accordance with its interface specification given in the
standard. Implementation details (like the above) are irrelevant.

If you explicitly put something like this into your own code, it becomes
a different story. It is indeed not portable, to say the least. The code
produces undefined behavior. But why would one want to do that anyway,
when you already have 'offsetof' in the standard library?
This means, it does work for quite a few different
platforms ( obviously with different implementations ), though it might
fail on some weird platform.
Yes. As it often turns out, the failing platform might not be as weird
as you expect.
Can we safely use this non-standard code in
places where we would have used a offsetof ?


"Safely" is a very stretchable word. Form the formal point of view of C
language - no, you can't. But, once again, why would anyone use it
instead of just using 'offsetof'?

--
Best regards,
Andrey Tarasevich
Nov 14 '05 #3

grid wrote:
Hi,
I recently came across a piece of code like this,
( & ( ( ( some struct * ) 0 ) -> element ) ) )

I had never seen this kind of code being used in any implementations so far, but somehow remembered to have seen it sometime in clc, and that it was for finding the offset of a member in a structure ( if I am not
horribly mistaken).

Now does this work ? Does this actually use the address 0x0, and when we cast it to the particular structure, and try to obtain the address of an element through this pointer, which turns out to be the offset of the member because the base address is 0x0.

Many of you might argue about portability,but I have seen this code work on multiple platforms.This means, it does work for quite a few different platforms ( obviously with different implementations ), though it might fail on some weird platform.Can we safely use this non-standard code in places where we would have used a offsetof ?

Thanx,
~


Define safely. As you point out it is possible for the code
to fail. On the other hand it is possible for an implementation
to have errors, or for a stray cosmic ray or two to mess up
an important register. So I guess the question is, is the danger
of using the construct low enough to to be outweighed by the
advantages [1].

The answer is, No. There are no advantages to using

( & ( ( ( some struct * ) 0 ) -> element ) ) )

rather than offsetof. If the above form works it will probably
be used by the implementation. If it does not work the implementation
will provide an offsetof that does work. Given that you are
going to wrap the ugly mess in a macro anyway (MY_OFFSETOF(foo))
you have gained percisely nothing [2].

- "William Hughes"
[1] This is the question that should be asked of any use
of a non portable construct. And very often the answer
is no, because there is no advantage [3] (often the question
is asked by people trying to outhink the implementation and
find efficiencies in intialization code that runs in
microseconds).

[2] It is possible that the implementation will provide a very
slow or broken offsetof. But in this case you have bigger
things to worry about than offsetof.

[3] There are cases where the general functions are not
adequate (e.g. cases where the malloc family of dynamic
memory allocation is not suitable). In this case a
specific and perhaps not fully portable solution may
be unavoidable. Still to first order: "If you have
to ask, the answer is no".

Nov 14 '05 #4
> [2] It is possible that the implementation will provide a very
slow or broken offsetof. But in this case you have bigger
things to worry about than offsetof.


I agree , but this does not stop implementors from using these
constructs for any gains (??) in performance . C is mostly popular
because of the power and flexibility it provides, though I am still
skeptical about the rationale behind this construct.

An offsetof macro could have done the trick , but the implementor chose
to use his own way, and as mentioned earlier , this code runs on many
popular UNIX platforms , so its not about an offsetof being broken or
slow for any particular platform.

~
Nov 14 '05 #5

grid wrote:
[2] It is possible that the implementation will provide a very
slow or broken offsetof. But in this case you have bigger
things to worry about than offsetof.
I agree , but this does not stop implementors from using these
constructs for any gains (??) in performance


a) (??) is right. offsetof is very unlikely to be
a performace bottleneck

b) implementors can (naturally) do whatever they like.
For an implementor, a non-portable trick that increases
performance is a GOOD THING.
C is mostly popular
because of the power and flexibility it provides, though I am still
skeptical about the rationale behind this construct.

The construct is clear enough. If the struct is at address zero, every
member will be at address offsetof(struct,member). The implementation
must know the offset of every member of every structure (how else
could the code be compiled?), but it may or may not recognize the
contruct as asking for this information. On the other hand
and implementation must recognize offsetof as asking for this
information.
An offsetof macro could have done the trick , but the implementor chose to use his own way,
??? An implementor cannot use the offsetof macro/function,
The implementor must provide the offsetof macro/function.
and as mentioned earlier , this code runs on many
popular UNIX platforms ,


How and whether the construct works is a property of the
implementation.
Two implementations on the same machine, or the same implementation
with different environment or optimization settings
(or even the same implementationat different times
(this is undefined behaviour) ) may do different
things. The OS probably has little influence. That said, the
construct will probably work. So what. There is no upside
to using it.
- William Hughes

Nov 14 '05 #6

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

Similar topics

13
by: James Harris | last post by:
Hi, Can someone recommend a book that will teach me how to approach C programming so that code is modularised, will compile for different environments (such as variations of Unix and Windows),...
8
by: suresh_C# | last post by:
Dear All, What is difference between Portable Executable (PE) file and a Assembly? Thanks, Mahesh
131
by: pemo | last post by:
Is C really portable? And, apologies, but this is possibly a little OT? In c.l.c we often see 'not portable' comments, but I wonder just how portable C apps really are. I don't write...
28
by: lovecreatesbeauty | last post by:
On gcc, which version of C standard has the most compliant: -c89, -ansi or c99? For more portable C code, which options should be applied to compilation? Can the following options guarantee the...
162
by: Richard Heathfield | last post by:
I found something interesting on the Web today, purely by chance. It would be funny if it weren't so sad. Or sad if it weren't so funny. I'm not sure which. ...
14
by: Kristan Dyson | last post by:
I was just wondering whether you knew whether it is possible to compile a fully portable C program? I want to write a 'C' CGI program on Windows, then just upload it to my Plus.Net Debian-based...
5
by: copx | last post by:
How portable are direct bit operations? Which ones are portable? I have never bothered learning such low-level stuff (I have an excuse: I am not a professional programmer), so I really don't know....
409
by: jacob navia | last post by:
I am trying to compile as much code in 64 bit mode as possible to test the 64 bit version of lcc-win. The problem appears now that size_t is now 64 bits. Fine. It has to be since there are...
7
by: jacob navia | last post by:
There are some people here (let's call them "regulars" for short) that are always giving lessons to people about how easy is to write portable code, etc. They always point fingers at you telling...
23
by: asit | last post by:
what is the difference between portable C, posix C and windows C ???
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
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
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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...
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,...
0
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...

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.