Question

I'm fairly new to C and are trying to write some basic applications with a seven segment display. When declaring the absolute address, for an 8-bit port I could write something like:

typedef char *port8ptr;
#define OUT_ADR 0x400
#define OUT *((port8ptr) OUT_ADR)

and then simply write to the variable out something like

OUT = 0x80;

to get Hexadecimal 80 to the port. But exactly what does the code above mean? That is, why does one define a pointer (line one) and then cast the address to be a pointer to a pointer (?!) ? It obviously works, but I don't really like using code from an example I can't understand.

Another way they did the type conversion was with the line

((unsigned char *) 0x400)

But I honestly don't get that either.

Many thanks in advance!

Axel

Was it helpful?

Solution

When you do all the preprocessing you get this line:

*((char*)0x400) = 0x80;

Let's dissect that. (char *)0x400 means take the number 0x400 and cast it to a "pointer-to-a-char". Basically it says here: let's create a pointer that points to address 0x400.

Then, we take that * in front of which means "dereference", making you can actually write something in the memory spot that the pointer points to, in this case address 0x400. And then you write 0x80 in it.

OTHER TIPS

The confusion here is the second line - you think it's a cast to a pointer to a pointer, while it's actually a dereference of a cast of a pointer.

Let's get back to the basics. Save you have a character and a pointer to that character

char c = 'A';
char *p = &c;

You can dereference p and get back to c - printf('%c', *p) will print A, and *p='B' will change c's content to B.

Another basic thing is casting an integer to a pointer - ((char *)0x400) means a pointer to the byte at address 0x400.

So the second line actually means 'write 0x80 to the byte at address 0x400'

The big difference between the language B and C, was that C added types. Thus you could specify an address for somewhere, and the type would tell the compiler whether it needed to load one, two, four or more bytes for that value. So, while you can point at any address in the system, you need to give the compiler addition information about how many bytes are at that location that you want loaded. These would all do different loads:

int x1= * ( unsigned char *) 0x400 ;
int x2= * ( unsigned short *) 0x400 ;
int x4= * ( unsigned int *) 0x400 ;

So x1 is going to have one byte of data from 0x400, while x4 is going to have four bytes. That's why you tell the compiler what's at the address, and then ask it to go look up the value there after.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top