473,804 Members | 2,998 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Help understading these proprocessor macros

Hi All,

I'm not that expert at C but I'm trying to understand some code that
does extensive use of the following two preprocessor macros:

#define WORD(ptr) (((*(octet *)(ptr))<<8)|(* (octet *)((ptr)+1)))
#define DWORD(ptr) (((*(octet *)(ptr))<<24)|( *(octet *)((ptr)+1)<<16 )|\
(*(octet *)((ptr)+2)<<8) |(*(octet *)((ptr)+3)))

I'm lost with all that shifting and indirection :-(
Could some kind soul explain what these macros are doing?

TIA,
David

Nov 14 '05 #1
5 1594
dr******@gmail. com writes:
I'm not that expert at C but I'm trying to understand some code that
does extensive use of the following two preprocessor macros:

#define WORD(ptr) (((*(octet *)(ptr))<<8)|(* (octet *)((ptr)+1)))
#define DWORD(ptr) (((*(octet *)(ptr))<<24)|( *(octet *)((ptr)+1)<<16 )|\
(*(octet *)((ptr)+2)<<8) |(*(octet *)((ptr)+3)))

I'm lost with all that shifting and indirection :-(
Could some kind soul explain what these macros are doing?


Presumably "octet" is a typedef for an 8-bit type, probably unsigned
char. (The code probably won't work on a system with CHAR_BIT!=8.)

WORD retrieves a 16-bit unsigned integer value, stored high-order byte
first (big-endian, also known as network order), pointed to by ptr.

DWORD retrieves a 32-bit unsigned integer value, stored
high-order-byte first (big-endian), pointed to by ptr.

Let's look at the definition of WORD, working from the inside out.

(ptr) is a pointer.

(octet *)(ptr) is ptr converted to a pointer-to-octet.

(*(octet *)(ptr)) dereferences the converted pointer, yielding an
octet value (a number in the range 0..255). Let's call this
HIGH_OCTET.

(ptr)+1 is points one element past the object pointed to by ptr. For
this to work properly, the actual argument passed to WORD had better
be of some character pointer type. If it's a void*, you can't legally
perform arithmetic on it. If it's an int*, for example, adding one
advances too far. If you wanted to allow WORD() to apply to arbitrary
pointer-to-void or pointer-to-object types, you'd want to add 1
*after* converting to (octet*). We'll assume that the argument is a
pointer-to-character.

(*(octet *)((ptr)+1)) retrieves the octet value from just after the
location pointed to by ptr. Let's call this LOW_OCTET.

The whole expression then becomes (HIGH_OCTET<<8| LOW_OCTET).

So, if ptr is of type unsigned char*, and *ptr==0x12, and
*(ptr+1)==0x34, then WORD(ptr) will be 0x1234.

Similarly, if ptr points to a sequence of unsigned bytes with the
values 0x12, 0x34, 0x56, and 0x78, DWORD(ptr) will be 0x12345678.

Note that if type int is 16 bits, the default integer promotions may
cause the DWORD() macro to fail, since there's nothing to indicate
that any of the operands are 32 bits. This could be corrected by
defining a 32-bit unsigned integer type (or using uint32_t) and
inserting several casts. But it may not be a problem if the code is
not required to be portable to such systems.

Both macros could be simplified to convert the pointer to a pointer to
the appropriate 16-bit or 32-bit type and dereference it, but *only*
if the machine uses a big-endian representation *and* the byte arrays
are appropriately aligned.

I suspect the macros are used in networking code, to extract 16-bit
and 32-bit unsigned integer values from network-order byte streams.

--
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.
Nov 14 '05 #2
In article <11************ **********@l41g 2000cwc.googleg roups.com>,
<dr******@gmail .com> wrote:
I'm not that expert at C but I'm trying to understand some code that
does extensive use of the following two preprocessor macros: #define WORD(ptr) (((*(octet *)(ptr))<<8)|(* (octet *)((ptr)+1)))
#define DWORD(ptr) (((*(octet *)(ptr))<<24)|( *(octet *)((ptr)+1)<<16 )|\
(*(octet *)((ptr)+2)<<8) |(*(octet *)((ptr)+3))) I'm lost with all that shifting and indirection :-(
Could some kind soul explain what these macros are doing?


octet -likely- maps to unsigned char . So for WORD, the code
takes the binary at the first character position, moves it 8 bits to the
left, and or's in the binary at the second position. The result
is going to be a 16 bit value (in a possibly wider integer type)
which is the concatenation of the bit values.

The code does not simply cast to a pointer to unsigned short for
a few reasons:

1) The pointer might not be properly aligned for an unsigned short;
2) an unsigned short is not necessarily two positions wide;
3) If char happens to be more than 8 bits wide in the implementation,
then grabbing a short would end up with a gap between the two 8
bit binary parts, whereas the code used will always put the 8 bit
parts together even if CHAR_BITS is more than 8
--
'ignorandus (Latin): "deserving not to be known"'
-- Journal of Self-Referentialism
Nov 14 '05 #3
ro******@ibd.nr c-cnrc.gc.ca (Walter Roberson) writes:
[snip]
The code does not simply cast to a pointer to unsigned short for
a few reasons:

1) The pointer might not be properly aligned for an unsigned short;
2) an unsigned short is not necessarily two positions wide;
3) If char happens to be more than 8 bits wide in the implementation,
then grabbing a short would end up with a gap between the two 8
bit binary parts, whereas the code used will always put the 8 bit
parts together even if CHAR_BITS is more than 8


CHAR_BIT, not CHAR_BITS.

If CHAR_BIT > 8, and some of the bytes being accessed happen to have
values greater than 255, there could be some overlap and incorrect
results. Running this code on a system with CHAR_BIT>8 would require
some careful thought; in particular, it's not clear how the octet
stream would be represented on a system with, say, 9-bit bytes.

Also:

4) The code assumes the data is represented in big-endian byte order;
if a short (assuming it's 16 bits, and assuming proper alignment) is
little-endian, casting the pointer to unsigned short* would yield
incorrect results.

--
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.
Nov 14 '05 #4
Many thanks Keith and Walter for your replys

Your explanations have been very good, just what I needed :-)

Just for clarification, the code is in fact reading values from the
header of a file wich are stored in network order (now I assume this is
the same as big endian) on pc/windows wich is not big endian.

The definition of octet found elsewhee in the source is:

typedef unsigned char octet;

So it seems you're right :-)

Example taken from the source:

#define HDR_NUMRECORDS 12
...
octet * pFile;
octet * pRecord;
int nRecords;
...
nRecords = WORD(pFile+HDR_ NUMRECORDS);

If I understood correctly this is assigning a 16 bit integer value
(short int fro this platform) to an int in inverse "endianness " of what
is stored at address pFile+HDR_NUMRE CORDS.

right?

Thanks again,
David

Nov 14 '05 #5
"mckennan" <dr******@gmail .com> writes:
[...]
The definition of octet found elsewhee in the source is:

typedef unsigned char octet;

So it seems you're right :-)

Example taken from the source:

#define HDR_NUMRECORDS 12
...
octet * pFile;
octet * pRecord;
int nRecords;
...
nRecords = WORD(pFile+HDR_ NUMRECORDS);

If I understood correctly this is assigning a 16 bit integer value
(short int fro this platform) to an int in inverse "endianness " of what
is stored at address pFile+HDR_NUMRE CORDS.

right?


Right. More precisely, it's retrieving a 16-bit big-endian value.
That happens to be the reverse of what your processor uses, but the
could should work equally well on a big-endian platform.

--
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.
Nov 14 '05 #6

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

Similar topics

1
1783
by: brian stanton | last post by:
ME AND A FRIEND OF MINE ARE MAKING A SITE THAT ALLOWS USERS TO CHAT RATE EACH OTHER UPLOAD PHOTOS OF THEM SELFS... (RATE BY LOOKS) AND IM EACH OTHER USEING LIKE A PHPBB LIKE SCRIPT ALSO A FORUM... ANY ONE KNOW OF ANY SCRIPTS... IF NOT
3
4086
by: tmponko | last post by:
OK...I'm new to this and I'm sure I'm missing something obvious, so please be kind. I've tried several different approaches to this problem (including various if, ifeq, and case constructs), and I'm about to give up. Can any tell me why this doesn't work? In a nutshell, I want a Makefile that will "include" either a Linux.mk or a SunOS.mk without having to rely on an explicit command line parameter or env var. Here is the segment that...
3
1580
by: J Krugman | last post by:
I'm trying to read some source code that makes very heavy use of macros and other pre-processor directives. To make matters worse, macro definitions are stacked several layers deep (i.e. macros are defined in terms of other macros, which are in turn defined in terms of other macros, seemingly ad infinitum). I tried reading the *.i files generated by the preprocessor (i.e. by giving gcc the -E flag). To my surprise, the macros were not...
3
2667
by: Stephen Sprunk | last post by:
On a project I'm working on, I ran across the following macros: /* assume s is struct stream *, s->p is char, v is unit16_t or uint32_t */ #define in_uint16_le(s,v) { v = *((s)->p++); v += *((s)->p++) << 8; } #define in_uint32_le(s,v) { in_uint16_le(s,v) \ v += *((s)->p++) << 16; v += *((s)->p++) << 24; } I'm personally not fond of function-like macros and wanted to turn these into static inline functions, but I'm having trouble doing...
14
2076
by: Malcolm | last post by:
Hi, I have the following which fails with "disagreement in number of macro arguments" when compiling with Imagecraft ICCAVR. Has anyone got any ideas - its not vital but would make the code a lot nicer to read: #define SET(x,y) (x |=(1<<y)) #define PIEZO PORTB,5
3
2354
by: OhMyGaw | last post by:
Hello Excel/automation Gurus, I am working on an application where I have to keep a centralized database of all macros distributed to user and save the changes back on a nightly basis back to one central Excel macro repository. What would you guys suggest me do? Should I keep all macros in a centralized unique text file of some sort or is it best to do with SQL server?
4
2141
by: Sreekanth | last post by:
Hi all, I have implemented a timing out version of fgets function call. I am pasting the entire code below. I have following doubts: 1. The code which I have written does it follow standard C programming conventions. ( I am pretty familar with java styles but not with c :-( ). 2. In order to read character by character from stdin , I have made use
9
2045
by: Jerret Johnson | last post by:
A challenged co-worker of mine challenged me to come up with a perverse example of a conforming Standard C program. This is by no means a gold medal winner in a C obfuscation contest, but nevertheless it demonstrates some arguably serious abuse of the preprocessor. If you can make it even more perverse, I'd appreciate it. And for those of you who might ask what my C question is ... is this Standard C? #include <ctype.h>
0
9579
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10332
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
10321
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,...
0
10077
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6853
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
5522
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
5651
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3820
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2991
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.