Using an unsigned integer to store a pointer in C

Nowadays, social networking is becoming quite “grown up” and goes a long way beyond teens discussing how to (mis)spend their time or posting 200 near identical and blurred photographs of last night’s awesome [sic] party. Although I do use Facebook, in a professional context I think that LinkedIn has much more value. Although it is essentially “Facebook for adults”, there is true potential for building a strong professional network, if you work in company or industry with global reach.

I particularly like some of the LinkedIn groups and I have recently been participating in a discussion about embedded C programming

This particular discussion topic is all about the use of pointers in C and whether it is OK to store the value of a pointer [i.e. an address] in an “ordinary” variable – like an unsigned integer. The specific example was in an embedded application – specifically in driver code. A simple way to express the idea in question is like this:

unsigned normal;
unsigned *pointer;
pointer = &normal;
normal = (unsigned)pointer;

This would result in the variable normal containing its own address. I will consider shortly whether this code would actually work or not.

In broad terms, most of the time, code should:

  1. perform the required function
  2. be readable/maintainable
  3. be readily portable to a different CPU

#3 may be considered less important in certain instances – like device drivers in embedded systems..

For most, but not all, modern CPUs, an address is the same bit size as a word of memory; i.e. most 32-bit CPUs have 32-bit address space as well as favoring operations on 32-bit data. In this context, most, but again not quite all, CPUs allow addresses to be stored in memory locations and registers and be operated on like any other data. Hence, the code above would be likely to work. Whether it is a good idea to write it is another matter.

To an assembly language programmer, manipulating addresses in this way is an everyday occurrence. It is the responsibility of the programmer to keep track of what is an address, what is an address of an address and what is data etc. There are also some high level languages – untyped languages – that operate in the same way; Forth and BCPL are examples that come to mind.

The majority of high level languages support data typing to a lesser or greater extent. This means, in effect, that the programmer specifies that a variable contains data or contains an address and the language only allows appropriate operations on that variable.

A possible area of confusion is between pointers and addresses. They are not one and the same thing. A pointer contains an address, for sure, but it also intrinsically knows about the kind of data that is stored at that address, which makes pointer arithmetic work correctly, but may be confusing to the newcomer. For example:

unsigned array[3];
unsigned *pointer;
pointer = array;
pointer++;

The incrementing of the pointer could also be written:

pointer += 1;

or

pointer = pointer + 1;

If array is at memory location 0×80000000, what is the value of pointer at the end of this code [on a 32-bit CPU]? The answer would be 0×80000004 because the compiler knows that the pointer needs to be moved 4 bytes at a time to move to the next array element. If you actually wanted to point to 0×80000001, you might need to write code like I started out with.

So, it all comes down to whether you want to work with a pointer or an address. Most of the time, a pointer does exactly what you want. However, there are special circumstances when you want to take an “assembly language” view in C code and this approach may be acceptable. But, I emphasize that this is only in special circumstances like a driver or maybe a debug monitor. Otherwise, such code is very unwise indeed.

Post Author

Posted December 16th, 2013, by

Post Tags

, ,

Post Comments

8 Comments

About The Colin Walls Blog

This blog is a discussion of embedded software matters - news, comment, technical issues and ideas, along with other passing thoughts about anything that happens to be on my mind. The Colin Walls Blog

Comments

8 comments on this post | ↓ Add Your Own

Commented on 17 December 2013 at 18:54
By horaira khan

Recently I have faced same situation, forced to use variable for storing the address, was in dilemma , thanks for clearing it out.
I have to use memory address contained in linker symbol in my application code for that I have used this

Commented on 23 December 2013 at 13:33
By Mark Garrett

I’m kind of surprised that you don’t bother with int in declarations i.e. unsigned int normal;
I assume thats economy of typing but then suggest all of the long forms of adding 1 and skip pointer++; ?

Commented on 23 December 2013 at 15:26
By Mark Garrett

Ignore that last comment I missed your initial example you did say pointer++;

Commented on 2 January 2014 at 14:13
By Alexei Fedorov

“The answer would be 0c80000004 ” Why 0c80000004??? Did you mean 0×80000004?

Commented on 3 January 2014 at 06:26
By Rahul Patel

Right, the next address using pointer++ or pointer += 1 would be 0×80000004. Hence if you want to work with individual byte or bits of 32-bit data that you store in memory, then you have to go with the assignment of pointer to unsigned int. This also is better approach then taking the 32-bit number and storing it in some temporary variable and then rotation, as this might be more complex and also may consume more memory (if memory is the constrained as in most OS based embedded system).

Commented on 6 January 2014 at 10:47
By Colin Walls

Thanks for spotting the typo Alexei – C is next to X on the keyboard. I have fixed it now.

Commented on 10 January 2014 at 13:06
By Ahmed Eissa

why would some one need to go to a address like 0×80000001 ( in behalf of your example ) ?

Commented on 10 January 2014 at 14:48
By Colin Walls

Ahmed: In order to access that specific byte. I would admit that there several other ways to achieve this objective.

Add Your Comment

You must be logged in to post a comment.

Archives