Re: [cc65] c question

From: Chiron Bramberger <chiron1bramberger.com>
Date: 2010-05-28 06:52:19
Thanks - this is great! I will meditate on all these responses.


On 27-May-10, at 7:21 AM, Mark J. Reed wrote:

On Thu, May 27, 2010 at 2:32 AM, Chiron Bramberger  
<chiron@bramberger.com> wrote:
But what does the * mean (on_the_right*)? I really want to truly  
understand this and not just how to "make it go". I want to get it.

It means the same thing, just from the other side. :)

Basically, the asterisk means "thing pointed to by".  So "*x" means  
"the thing pointed to by x".

Thus, the declaration "int *x" means "the thing pointed to by x is an  
integer".  But that doesn't make much sense; you're not declaring the  
thing pointed to by x.  Instead, you're declaring x.  What is the  
type of x?  If you slide the * over  to get  "int* x", then the rules  
of C declarations tell you that x is of type "int*".  So "int *"  
means "pointer to int".

More generally, the trailing * only shows up in type expressions, and  
means that the type under discussion is a pointer to whatever type  
came before the *.  (The * is one of the things that gives C "type  
expressions" instead of just type names.)

Type expressions are important because  a pointer is not just a  
memory address; it's a memory address plus information about what is  
expected to be found at that memory address.  A memory address by  
itself is not useful in C - you can't dereference it until the  
compiler knows what type of value to retrieve from it.  You do that  
by typecasting - putting a type expression in parentheses in front of  
a value tells the compiler "treat this value as this type".

Typecasting by itself has nothing to do with pointers . . . (int) x  
means "treat x as an integer", and can be used whether x is a char or  
an unsigned int or a float or whatever.  This is very useful for  
pointers because the original meaning of * depends heavily on the  
type of what comes after.  If x is a pointer to int, then *x is an  
int.  If x is a pointer to char, then *x is a char.  But if you  
combine the dereferencing with typecasting, you can get any kind of  
value out of any pointer.  Which lets you do the C equivalent of  
PEEK, among other things.

For example, pretend that at address 0xC000 you have the two bytes  
0x01 and 0x02.  Then:

*((char *)0xC000)  is the character '\01'.

  *((int *)0xC000) the integer value 0x0201.

Note that that this assignment:

int x  = *((char *)0xC000);

Will assign 1 to x, not 0x0201.  The whole value is cast to an int  
because it's being assigned to an integer variable; you could make  
that explicit with another typecast:

int x = (int)(*((char *)0xC000));

but that doesn't change how the pointer is dereferenced.  The inner  
typecast does that, and you only ever get a char value out of the  
expression.

Types are tied to sizes, and this matters when you do arithmetic on  
pointer values, because offsets are automatically multiplied by the  
size of the thing pointed to.  So given this:

int *x = (int *)0xC000;

Then x+1 is not pointing to 0xC001 but 0xC002.  This is how arrays  
work in C: the compiler turns foo[bar] into *(foo+bar).


-- 
Mark J. Reed <markjreed@gmail.com>



----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo@musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.
Received on Fri May 28 06:52:28 2010

This archive was generated by hypermail 2.1.8 : 2010-05-28 06:52:33 CEST