I'm trying to understand some sample C code that I got with my microcontroller board. I have a really hard time to understand that whole pointer thing. I read a lot of posts in this forum and I also read several tutorials and slowly I get the hang of it :) But...
In my sample code there is the following line of code, which I could not decrypt with any information that I have found yet.
#define SOMENAME ((uint32_t *)0x130010f0)
I understood, that #define simply replaces all occurrences of SOMENAME in the compiled code with the respective statement (don't know if this is correctly explained, but I really think I got what this is doing).
Now, what I could imagine, what the rest of the statement means is the following:
SOMENAME is now a pointer to the address 0x130010f0 but without being an actual variable.
Is this correct? And I could kind of use it for example as: printf("value at address 0x130010f0: %p",SOMENAME) because the compiler would replace it with printf("value at address 0x130010f0: %p",((uint32_t *)0x130010f0)) and this gives the value stored at that address? What would be the print statement if I want the address of that pointer? I can't, right? Because the pointer does not have an address as it is not a variable? Very confusing...
The example is quite complex and this definition is also part of other definitions which are pointers to structs of structs of structs, therefore this "simple" example. Below you can find the "whole" structure:
#define ROM_API_TREE ((uint32_t *)0x130010f0)
#define BOOTLOADER_POINTER ((bootloader_tree_t *)ROM_API_TREE)
flash_driver_interface_t *FLASH_API_TREE
#define FLASH_API_TREE BOOTLOADER_POINTER->flashDriver
typedef struct BootloaderTree{
...
const flash_driver_interface_t *flashDriver;
} bootloader_tree_t
typedef struct FlashDriverInterface{
...
status_t (*ffr_get_uuid)(flash_config_t *config, uint8_t *uuid);
} flash_driver_interface_t
/*
* I actually want to understand that statement, but as I fail
* already at the beginning, I posted this question
*/
status_t = FLASH_API_TREE->ffr_get_uuid(config,uuid);
You are correct that SOMENAME get replaced by the preprocessor with ((uint32_t *)0x130010f0). What this gives you is a pointer to a uint32_t, and the value of that pointer is 0x130010f0.
When you then do this:
printf("value at address 0x130010f0: %p",SOMENAME);
You'll actually print the value of the pointer, i.e. 0x130010f0, not what it points to. For that you would need to dereference it, i.e.:
printf("value at address 0x130010f0: %u", *SOMENAME);
This however assumes that 0x130010f0 is a valid address that can be dereferenced and read. This will typically only be the case in some particular embedded environment where the implementation allows it.
As i saw, you basically could understand many things behind the Pointers. The SOMENAME is a macro not a variable right. Before i get to the code, a pointer in general is nothing else but a variable that contains an adress instead of having a value.
printf("value at address 0x130010f0: %p",SOMENAME); is wrong because the %p expects a value not an Adress and you are passing the adress to it, so you all you have to do is to dereference it using the *.
When you write (uint32_t *)0x130010f0 you are casting the adress to the type writteb between parentheses.
Whenever it gets complicated while using pointers try to remember this small example:
int a = 10;
int *p = &a;// declare pointer of type integer. This is valid, adress of an integer variable contains adress of integer variable
int *j; //declare pointer of type integer
j = &a; //correct, because j expects an adress.
*j = &a; //wrong *j expects a value
printf("value of p: %p", *p);
printf("adress of p: %p", p); //or &p
This shows that your microcontroller board has a program accessible 32-bit device.
I say 'accessible' because this device could be readable, writable or both.
I use the kinda general term 'device' because it could be all kinds of things. Quite often it's a register that simply stores a value, but it could also be a FIFO chip returning the next stored value at every read.
Assuming it's a register: These registers often consist of separate bits or small groups of bits to represent some function. In that case you'd see bitfield struct declarations that look like this (two 16-bit fields as example):
struct {
uint32_t someField : 16;
uint32_t otherField : 16;
} fields;
Related
I'm dealing with pointers, double-pointers and arrays, and I think I'm messing up a bit my mind. I've been reading about it, but my particular user-case is messing me up, and I'd appreciate if someone could clear a bit my mind. This is a small piece of code I've built to show my misunderstanding:
#include <stdio.h>
#include <stdint.h>
void fnFindValue_vo(uint8_t *vF_pu8Msg, uint8_t vF_u8Length, uint8_t **vF_ppu8Match, uint8_t vF_u8Value)
{
for(int i=0; i<vF_u8Length; i++)
{
if(vF_u8Value == vF_pu8Msg[i])
{
*vF_ppu8Match = &vF_pu8Msg[i];
break;
}
}
}
int main()
{
uint8_t u8Array[]={0,0,0,1,2,4,8,16,32,64};
uint8_t *pu8Reference = &u8Array[3];
/*
* Purpose: Find the index of a value in u8Array from a reference
* Reference: First non-zero value
* Condition: using the function with those input arguments
*/
// WAY 1
uint8_t *pu8P2 = &u8Array[0];
uint8_t **ppu8P2 = &pu8P2;
fnFindValue_vo(u8Array,10,ppu8P2,16); // Should be diff=4
uint8_t u8Diff1 = *ppu8P2 - pu8Reference;
printf("Diff1: %u\n", u8Diff1);
// WAY 2
uint8_t* ppu8Pos; // Why this does not need to be initialized and ppu8P2 yes
fnFindValue_vo(u8Array,10,&ppu8Pos,64); // Should be diff=6
uint8_t u8Diff2 = ppu8Pos - pu8Reference;
printf("Diff2: %u\n", u8Diff2);
}
Suppose the function fnFindValue_vo and its arguments cannot be changed. So my purpose is to find the relative index of a value in the array taking as reference the first non-zero value (no need to find it, can be hard-coded).
In the first way, I've done it following my logic and understanding of the pointers. So I have *pu8P2 that contains the address of the first member of u8Array, and **ppu8P2 containing the address of pu8P2. So after calling the funcion, I just need to substract the pointers 'pointing' to u8Array to get the relative index.
Anyway, I tried another method. I just created a pointer, and passed it's address, without initializing the pointer, to the funcion. So later I just need to substract those two pointers and I get also the relative index.
My confusion comes with this second method.
Why ppu8Pos does not have to be initialized, and ppu8P2 yes? I.e. Why couldn't I declare it as uint8_t **ppu8P2;? (it gives me Segmentation fault).
Which of the two methods is more practical/better practice for coding?
Why is it possible to give the address to a pointer when the function's argument is a double pointer?
Why ppu8Pos does not have to be initialized, and ppu8P2 yes
You are not using the value of ppu8Pos right away. Instead, you pass its address to another function, where it gets assigned by-reference. On the other hand, ppu8P2 is the address of ppu8Pos you pass to another function, where its value is used, so you need to initialise it.
Which of the two methods is more practical/better practice for coding
They are identical for all intents and purposes, for exactly the same reason these two fragments are identical:
// 1
double t = sin(x)/cos(x);
// 2
double s = sin(x), c = cos(x);
double t = s/c;
In one case, you use a variable initialised to a value. In the other case, you use a value directly. The type of the value doesn't really matter. It could be a double, or a pointer, or a pointer to a pointer.
Why is it possible to give the address to a pointer when the function's argument is a double pointer?
These two things you mention, an address to a pointer and a double pointer, are one and the same thing. They are not two very similar things, or virtually indistinguishable, or any weak formulation like that. No, the two wordings mean exactly the same, to all digits after the decimal point.
The address of a pointer (like e.g. &pu8P2) is a pointer to a pointer.
The result of &pu8P2 is a pointer to the variable pu8P2.
And since pu8P2 is of the type uint8_t * then a pointer to such a type must be uint8_t **.
Regarding ppu8Pos, it doesn't need to be initialized, because that happens in the fnFindValue_vo function with the assignment *vF_ppu8Match = &vF_pu8Msg[i].
But there is a trap here: If the condition vF_u8Value == vF_pu8Msg[i] is never true then the assignment never happens and ppu8Pos will remain uninitialized. So that initialization of ppu8Pos is really needed after all.
The "practicality" of each solution is more an issue of personal opinion I believe, so I leave that unanswered.
For starters the function fnFindValue_vo can be a reason of undefined behavior because it does not set the pointer *vF_ppu8Match in case when the target value is not found in the array.
Also it is very strange that the size of the array is specified by an object of the type uint8_t. This does not make a sense.
The function should be declared at least the following way
void fnFindValue_vo( const uint8_t *vF_pu8Msg, size_t vF_u8Length, uint8_t **vF_ppu8Match, uint8_t vF_u8Value )
{
const uint8_t *p = vF_pu8Msg;
while ( p != vF_pu8Msg + vF_u8Length && *p != vF_u8Value ) ++p;
*vF_ppu8Match = ( uint8_t * )p;
}
The difference between the two approaches used in your question is that in the first code snippet if the target element will not be found then the pointer will still point to the first element of the array
uint8_t *pu8P2 = &u8Array[0];
And this expression
uint8_t u8Diff1 = *ppu8P2 - pu8Reference;
will yield some confusing positive value (due to the type uint8_t) because the difference *ppu8P2 - pu8Reference be negative.
In the second code snippet in this case you will get undefined behavior due to this statement
uint8_t u8Diff2 = ppu8Pos - pu8Reference;
because the pointer ppu8Pos was not initialized.
Honestly, not trying to understand your code completely, but my advice is do not overcomplicate it.
I would start with one fact which helped me untangle:
if you have int a[10]; then a is a pointer, in fact
int x = a[2] is exactly the same like int x = *(a+2) - you can try it.
So let's have
int a[10]; //this is an array
//a is a pointer to the begging of the array
a[2] is an int type and it is the third value in that array stored at memory location a plus size of two ints;
&a[2] is a pointer to that third value
*(a) is the first value in the array a
*(a+1) is the same as a[1] and it is the second int value in array a
and finally
**a is the same as *(*a) which means: *a is take the first int value in the array a (the same as above) and the second asterisk means "and take that int and pretend it is a pointer and take the value from the that location" - which is most likely a garbage.
https://stackoverflow.com/questions/42118190/dereferencing-a-double-pointer
Only when you have a[5][5]; then a[0] would be still a pointer to the first row and a[1] would be a pointer to the second row and **(a) would then be the same as a[0][0].
https://beginnersbook.com/2014/01/2d-arrays-in-c-example/
Drawing it on paper as suggested in comments helps, but what helped me a lot is to learn using debugger and break points. Put a breakpoint at the first line and then go trough the program step by step. In the "watches" put all variants like
pu8P2,&pu8P2,*pu8P2,**pu8P2 and see what is going on.
As I understand it, all of the cases where C has to handle an address involve the use of a pointer. For example, the & operand creates a pointer to the program, instead of just giving the bare address as data (i.e it never gives the address without using a pointer first):
scanf("%d", &foo)
Or when using the & operand
int i; //a variable
int *p; //a variable that store adress
p = &i; //The & operator returns a pointer to its operand, and equals p to that pointer.
My question is: Is there a reason why C programs always have to use a pointer to manage addresses? Is there a case where C can handle a bare address (the numerical value of the address) on its own or with another method? Or is that completely impossible? (Being because of system architecture, memory allocation changing during and in each runtime, etc). And finally, would that be useful being that addresses change because of memory management? If that was the case, it would be a reason why pointers are always needed.
I'm trying to figure out if the use pointers is a must in C standardized languages. Not because I want to use something else, but because I want to know for sure that the only way to use addresses is with pointers, and just forget about everything else.
Edit: Since part of the question was answered in the comments of Eric Postpischil, Michał Marszałek, user3386109, Mike Holt and Gecko; I'll group those bits here: Yes, using bare adresses bear little to no use because of different factors (Pointers allow a number of operations, adresses may change each time the program is run, etc). As Michał Marszałek pointed out (No pun intended) scanf() uses a pointer because C can only work with copies, so a pointer is needed to change the variable used. i.e
int foo;
scanf("%d", foo) //Does nothing, since value can't be changed
scanf("%d", &foo) //Now foo can be changed, since we use it's address.
Finally, as Gecko mentioned, pointers are there to represent indirection, so that the compiler can make the difference between data and address.
John Bode covers most of those topics in it's answer, so I'll mark that one.
A pointer is an address (or, more properly, it’s an abstraction of an address). Pointers are how we deal with address values in C.
Outside of a few domains, a “bare address” value simply isn’t useful on its own. We’re less interested in the address than the object at that address. C requires us to use pointers in two situations:
When we want a function to write to a parameter
When we need to track dynamically allocated memory
In these cases, we don’t really care what the address value actually is; we just need it to access the object we’re interested in.
Yes, in the embedded world specific address values are meaningful. But you still use pointers to access those locations. Like I said above, a pointer is an address for our purposes.
C allows you to convert pointers to integers. The <stdint.h> header provides a uintptr_t type with the property that any pointer to void can be converted to uintptr_t and back, and the result will compare equal to the original pointer.
Per C 2018 6.3.2.3 6, the result of converting a pointer to an integer is implementation-defined. Non-normative note 69 says “The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.”
Thus, on a machine where addresses are a simple numbering scheme, converting a pointer to a uintptr_t ought to give you the natural machine address, even though the standard does not require it. There are, however, environments where addresses are more complicated, and the result of converting a pointer to an integer may not be straightforward.
int i; //a variable
int *p; //a variable that store adres
i = 10; //now i is set to 10
p = &i; //now p is set to i address
*p = 20; //we set to 20 the given address
int tab[10]; // a table
p = tab; //set address
p++; //operate on address and move it to next element tab[1]
We can operate on address by pointers move forward or backwards. We can set and read from given address.
In C if we want get return values from functions we must use pointers. Or use return value from functions, but that way we can only get one value.
In C we don't have references therefore we must use pointers.
void fun(int j){
j = 10;
}
void fun2(int *j){
*j = 10;
}
int i;
i = 5; // now I is set to 5
fun(i);
//printf i will print 5
fun2(&i);
//printf I will print 10
I don't know if I even asked the question correctly, but I've been struggling to wrap my head around the following lines of code and wasn't able to find an answer that I could understand.
#define GPIO_LED ((uint32_t *)0x510000A0)
*(GPIO_LED ) = (uint32_t *)num;
where num is an integer (between 0 and 255)
Okay. ((uint32_t *)0x510000A0) is a constant of type pointer to uint32_t -- in other words, an explicitly declared absolute address.
*(GPIO_LED ) = (uint32_t *)num; typecasts the value in num into a pointer to uint32_t, and then assigns it at the location with the absolute addtress 0x510000A0.
The effect is it's putting the value num into the program's memory space at address 0x510000A0.
This sort of trick is often used in low-level programming to put settings into a memory address that's mapped to some physical device control.
update
Yeah, yeah, I got lost in the asterisks. uint32_t pointer.
I have read what I could find on pointers in C/C++ but most of it is introductory, and while it helps you to understand using them there are many cases where existing code throws examples that are troublesome to decipher.
I did see some examples where they break down a line of code into what it really means and some of the more complex ones end up with something like: "a pointer to a function that returns a pointer to a pointer of an int"
Ok great, but what kind of scenario would you run into where you would end up with this? Is this sort of pointer situation something that comes up often? It does not seem very readable and if you had code full of this I could see a great possibility of bugs popping up.
I have found one line of code in a library that I do not fully understand but it is not quite the crazy deciphered example listed above:
*(uint8_t *)&(SPI2->DR) = SPI2_DATA;
SPI2_DATA is getting assigned to the DR of SPI2, but what is all that other code for?
As far as I can tell the code is doing a bitwise AND between a pointer to a uint8_t and the DR of SPI2 and then dereferencing the whole thing to assign SPI2_DATA to it. I know that is not right though?
You should decompose the instruction to fully understand what happens:
*(uint8_t *)&(SPI2->DR) = SPI2_DATA
&SPI->DR obtains the address of the variable DR in struct/class SPI, this address has type Something* where Something is the type of DR.
Then this address is casted to uint8_t*, so it is casted to a pointer to a uint8_t, which is a fixed width unsigned integer of 1 byte.
Finally this address is dereferenced to assign SPI2_DATA to it.
Something like:
Something* temp1 = &SPI2->DR;
uint8_t* temp2 = (uint8_t*)temp1;
*temp2 = SPI2_DATA;
Here's an example of what it does:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#define SPI2_DATA 0xfc
struct spi {
uint16_t DR;
};
int main ( void ) {
struct spi * SPI2 = malloc(sizeof(*SPI2));
SPI2->DR = 0x3210; /* some initial value chosen on a whim */
printf("before: %04x\n", SPI2->DR);
*(uint8_t *)&(SPI2->DR) = SPI2_DATA;
printf(" after: %04x\n", SPI2->DR);
return 0;
}
before: 3210
after: 32fc
Note how only 8 bits of the value changed.
SPI2->DR is probably declared as a pointer, but not a pointer to the type uint8_t (maybe it's declared as a pointer to void). SPI2_DATA is of type uint8_t. So in order to copy SPI2_DATA into the target of SPI2->DR, the code is getting the pointer using &, converting the pointer to the correct type with a cast, then dereferencing it.
Yesterday while I was coding in C, my friend asked me pointing to a variable is it pointer or a variable ? I stucked up for a while. I didnt find an aswer to it , I just have to go back and search it and tell him.But I was thinking is there any function to differentiate them.
Can we differentiate a variable against a pointer variable
int a;
sizeof(a); // gives 2 bytes
int *b;
sizeof(b); // gives 2 bytes
// if we use sizeof() we get same answer and we cant say which is pointer
// and which is a variable
Is there a way to find out a variable is a normal variable or a pointer? I mean can someone say that it is a pointer or a variable after looking at your variable that you have declared at the beginning and then going down 1000 lines of your code?
After the comment
I wanted to say explicitly it's a 16 bit system architecture.
First, the question "Is it a pointer or a variable" doesn't make much sense. A pointer variable is a variable, just as an integer variable, or an array variable, is a variable.
So the real question is whether something is a pointer or not.
No, there's no function that can tell you whether something is a pointer or not. And if you think about it, in a statically typed language like C, there can't be. Functions take arguments of certain specified types. You can't pass a variable to a function unless the type (pointer or otherwise) is correct in the first place.
You mean differentiate them at run time without seeing the code? No, you can't. Pointers are variables that hold memory address. You can't check it at run time. That means, there is no such function isPointer(n) that will return true/false based on parameter n.
You can deduce the type from the use.
For example:
char* c;
...
c[0] = 'a';
*c = 'a';
Indexing and dereferencing would let you know it's a pointer to something (or it's an array if defined as char c[SOME_POSITIVE_NUMBER];).
Also, things like memset(c,...), memcpy(c,...) will suggest that c is a pointer (array).
OTOH, you can't normally do with pointers most of arithmetic, so, if you see something like
x = c * 2;
y = 3 / c;
z = c << 1;
w = 1 & c;
then c is not a pointer (array).
Three things:
What platform are you using where sizeof(int) returns 2? Seriously
Pointers are types. A pointer to an int is a type, just like an int is. The sizes of a type and a pointer to that type are sometimes equal but not directly related; for instance, a pointer to a double (on my machine, at least) has size 4 bytes while a double has size 8 bytes. sizeof() would be a very poor test, even if there was a situation where such a test would be appropriate (there isn't).
C is a strictly typed language, and your question doesn't really make sense in that context. As the programmer, you know exactly what a is and you will use it as such.
If you'd like to be able to tell whether a variable is a pointer or not when you see it in the source code, but without going back to look at the declaration, a common approach is to indicate it in the way you name your variables. For example, you might put a 'p' at the beginning of the names of pointers:
int *pValue; /* starts with 'p' for 'pointer' */
int iOther; /* 'i' for 'integer' */
...or even:
int *piSomething; /* 'pi' for 'Pointer to Integer' */
This makes it easy to tell the types when you see the variable in your code. Some people use quite a range of prefixes, to distinguish quite a range of types.
Try looking up "Hungarian notation" for examples.
no , you can't.
and what is the usage, as each time u run the code the pointer address will be different ?? however u can subtract two pointers and also can get the memory address value of any pointer.