C pointers: How do pointers hold memory address that are larger than their datatype allows?

Thread Starter

odm4286

Joined Sep 20, 2009
265
For example, if I have....

Code:
char mychar;
mychar = 'd'
char* ptr = &mychar;
putc(*ptr, stdout);
This should output the value held inside mychar, now that much makes perfect sense to me. What doesn't is how the memory address of mychar is stored. Lets say &mychar is FAR greater that 0xFF, in most cases it will be, how does ptr hold a value that is larger than a char is capable of holding?
 

nsaspook

Joined Aug 27, 2009
13,079
The pointer (a variable usually stored in a computer word sized memory location) simply holds the memory address of another variable location of the specified size for the pointed to variable type.

Pointer a points to variable b
 

Thread Starter

odm4286

Joined Sep 20, 2009
265
The pointer (a variable usually stored in a computer word sized memory location) simply holds the memory address of another variable location of the specified size for the pointed to variable type.

Pointer a points to variable b
That makes sense, so the size of the pointer is usually the same and the datatype only determines how many bytes to increment or decrement by when doing pointer arithmetic? Also, I'm doing some embedded programming with a PIC16F1619. Is there any way to know exactly where the compiler stores my pointer?

I'm trying to slog my way through an RTOS and I'm working on some memory mapping routines.
 

MrChips

Joined Oct 2, 2009
30,702
You are confusing the address of a variable and the storage allocated to the variable.
A char typically can be stored in 8 bits.
The address of mychar can be any size depending on the architecture of the computer and the compiler.
If the address is 64 bits (for example), then a pointer such as ptr has to store 64 bits. The size of char mychar is irrelevant.
 

Thread Starter

odm4286

Joined Sep 20, 2009
265
You are confusing the address of a variable and the storage allocated to the variable.
A char typically can be stored in 8 bits.
The address of mychar can be any size depending on the architecture of the computer and the compiler.
If the address is 64 bits (for example), then a pointer such as ptr has to store 64 bits. The size of char mychar is irrelevant.
That makes sense, thank you
 

Thread Starter

odm4286

Joined Sep 20, 2009
265
The pointer variable with no operator is the address of the pointer.

int *p;
printf("Address of variable num is: %p", p);

http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Pointers.html
I don't quite follow. If I do the following declarations and initializations...

int i;
int* p = i;

I understand that p now points to i, in other words *p = i and p = &i
but.... &p must have a value. The pointer MUST be stored somewhere in memory right?
 

MrChips

Joined Oct 2, 2009
30,702
Is there any way to know exactly where the compiler stores my pointer?
If you look at the map file generated by the linker it will show where all variables are located.
Also if you invoke a breakpoint while debugging, you should be able to view all variables, indicating addresses and contents.
 

WBahn

Joined Mar 31, 2012
29,976
I don't quite follow. If I do the following declarations and initializations...

int i;
int* p = i;

I understand that p now points to i, in other words *p = i and p = &i
but.... &p must have a value. The pointer MUST be stored somewhere in memory right?
A pointer is just another data type, just like char, int, or double.

Given the declaration

int i;

if you want to know the address where the variable i is stored, then you can use:

printf("The variable 'i' is stored at location %p\n", &i);

If you have

int *p;

and what to know the address where that variable is stored, then you can use:

printf("The variable 'p' is stored at location %p\n", &p);

There's nothing magical about it.

Now, your code

int* p = i;

should at the very least throw a warning. The value stored in 'i' is a value of type 'int'. But 'p' is of type 'pointer to an int' and the value you store in it needs to be an address.

So it would need to be

int *p = &i;

Notice also that I moved the * so that it is associated with the variable and not with the type. Either way is treated the same in this case. Using 'int*' implies that the type of data on that line is an 'int*'. But that not actually the case. This can most clearly be seen by considering what happens if you had two pointers that you wanted to declare at the same time. The way you have written would make it seem like the way to do this is

int* i, j;

But if you do this, then 'i' is a pointer to an 'int', but 'j' is just a regular old 'int'. What you need to do is

int *i, *j;

So it is best to write your code so that the '*' is visually bound to the variable name and not the data type.
 

nsaspook

Joined Aug 27, 2009
13,079
The pointer MUST be stored somewhere in memory right?
Yes, if you print the value of p that will be the memory address of the pointer variable p. The data in that memory location p ( with a dereference operator or indirection operator) will point to another location with a l-value (usually but it can also point to a functions code location).
http://www.c4learn.com/c-programming/accessing-value-and-address-of-pointer/

As has been said there is nothing special memory-wise about pointers but there are datatype rules about how math functions operate on them.

http://www.c4learn.com/c-programming/c-incrementing-pointer/
 
Last edited:

WBahn

Joined Mar 31, 2012
29,976
Yes, if you print the value of p that will be the memory address of the pointer variable p. The data in that memory location p ( with a dereference operator or indirection operator) will point to another location with a l-value (usually but it can also point to a functions code location).
http://www.c4learn.com/c-programming/accessing-value-and-address-of-pointer/

As has been said there is nothing special memory-wise about pointers but there are datatype rules about how math functions operate on them.

http://www.c4learn.com/c-programming/c-incrementing-pointer/
If you print the value of p, what you will get is the value that is stored in the variable p, NOT the memory address of the p. Just like if you print the value of i, you will get the value that is stored in the variable i and not the memory address of i.

So if you print the value of p, you will get the memory address of the variable that p points to (in the recent examples, the address at which 'i' is stored).
 

ArakelTheDragon

Joined Nov 18, 2016
1,362
First this is a cometely wrong code or questions.

Char* is a cast and has nothing to do with pointers. It only shows the expected result in the variable will be a char.

*ptr is a pointer. If it is "Char *ptr" the data inside of whatever you are pointing will be of type Char.

*ptr is not associated with addresses, but only with data.

&ptr will return the address of the variable.

Read the Karnighan & Ritchie C book, second edition.
 

Thread Starter

odm4286

Joined Sep 20, 2009
265
Yes, if you print the value of p that will be the memory address of the pointer variable p. The data in that memory location p ( with a dereference operator or indirection operator) will point to another location with a l-value (usually but it can also point to a functions code location).
http://www.c4learn.com/c-programming/accessing-value-and-address-of-pointer/

As has been said there is nothing special memory-wise about pointers but there are datatype rules about how math functions operate on them.

http://www.c4learn.com/c-programming/c-incrementing-pointer/

Thanks, I understand pointers well enough. My trouble is the following. I'm trying to hack my way through a simple RTOS on an 8 bit PIC. Now I'm going through the datasheet and I find some blocks of memory in the general purpose registers that I THINK I can use freely.

I'm writing a function that uses a pointer to reference the first block in bank 0 for example. This way I can iterate through using the other until I reach the last block of memory and allocate as needed.

The part I'm trying to wrap my head around is the idea of "controlling" where that pointer is stored. Not the actual data it points to, that I feel like I understand.
 

nsaspook

Joined Aug 27, 2009
13,079
Thanks, I understand pointers well enough. My trouble is the following. I'm trying to hack my way through a simple RTOS on an 8 bit PIC. Now I'm going through the datasheet and I find some blocks of memory in the general purpose registers that I THINK I can use freely.

I'm writing a function that uses a pointer to reference the first block in bank 0 for example. This way I can iterate through using the other until I reach the last block of memory and allocate as needed.

The part I'm trying to wrap my head around is the idea of "controlling" where that pointer is stored. Not the actual data it points to, that I feel like I understand.
As @WBahn clarified, a pointer is just another variable in memory space.
If you want to store them at a specific location in XC8: http://microchipdeveloper.com/faq:38

int foobar @ 0x80;
 

WBahn

Joined Mar 31, 2012
29,976
First this is a cometely wrong code or questions.

Char* is a cast and has nothing to do with pointers. It only shows the expected result in the variable will be a char.

*ptr is a pointer. If it is "Char *ptr" the data inside of whatever you are pointing will be of type Char.

*ptr is not associated with addresses, but only with data.

&ptr will return the address of the variable.

Read the Karnighan & Ritchie C book, second edition.
There is no data type 'Char' in C, it's 'char'.

char* is no more cast than double is.

If you want to cast a value to be a pointer to a value of type char, then you cast it the same way that you cast value of type int to be a double.

For instance, with a 32-bit compiler on a little-endian machine, the following code will normally produce

C:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   int k = 6451010;
   
   printf("%s\n", (char *) &k);

   return EXIT_SUCCESS;
}
Bob

as the output without throwing any warnings. But if the cast (char *) is omitted it will likely throw a warning on a more recent compiler because the first argument is expecting a pointer to a 'char' and &k is a pointer to an 'int'. But the cast forces the compiler to convert it to a pointer to a 'char' before using it. Since, on most compilers, the only difference is how the compiler interprets the data stored at the address pointed to and there is no difference in the form or interpretation of the pointers themselves, there is no actual manipulation that takes place.
 

ArakelTheDragon

Joined Nov 18, 2016
1,362
There is no data type 'Char' in C, it's 'char'.

char* is no more cast than double is.

If you want to cast a value to be a pointer to a value of type char, then you cast it the same way that you cast value of type int to be a double.

For instance, with a 32-bit compiler on a little-endian machine, the following code will normally produce

C:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   int k = 6451010;
  
   printf("%s\n", (char *) &k);

   return EXIT_SUCCESS;
}
Bob

as the output without throwing any warnings. But if the cast (char *) is omitted it will likely throw a warning on a more recent compiler because the first argument is expecting a pointer to a 'char' and &k is a pointer to an 'int'. But the cast forces the compiler to convert it to a pointer to a 'char' before using it. Since, on most compilers, the only difference is how the compiler interprets the data stored at the address pointed to and there is no difference in the form or interpretation of the pointers themselves, there is no actual manipulation that takes place.
I think we understand that is a typo!

I have not seen a little endian embedded machine with a PIC16.
 

WBahn

Joined Mar 31, 2012
29,976
I think we understand that is a typo!

I have not seen a little endian embedded machine with a PIC16.
Why should we understand that it is a type, since Char is a data type in several languages.

The original question is about C pointers. But, if you want to use a big-endian machine, fine. In the example I gave, set k equal to 1,113,747,200 (provided the compiler uses 32-bit ints -- if it doesn't then we can set the value to some other number).

And none of that changes the fact that char* is NOT a cast.
 

nsaspook

Joined Aug 27, 2009
13,079
My own, writing it from scratch. Pray for me.
No need, every budding future systems programmer designs an OS or two while learning. It's a good exercise in programming but mainly useless IMO as a practical matter on simple 8 bit machines as a improvement over big loop state machines and interrupt/dma driven I/O for optimized targeted applications. 10 years ago the 'industry pundits' declared 8-bit controllers dead because we would need all the fancy services of a >8-bit OS for fancy future applications. It's true that the complexity of even a simple thing like a ADC can be bewildering on 32-bit machines so having an RTOS abstraction layer helps but it mainly gets in the way of directly interacting with limited program state to hardware on a 8-bit machines simper interfaces in a sequential manner instead of partitioned tasks, scheduler and queues with a RTOS.
 
Top