double stars in pointer definition - c

I have a come across following definition in an embedded code:
#define REG_ADD 0x20081004
#define pREG ((void * volatile *)REG_ADD)
Why there are 2 * in pREG definition? What does it mean?

void** is a pointer to pointer-to-void.
void * volatile * is a pointer to volatile-qualified-pointer-to-void. (Read the declaration right-to-left, pretty much. See this.)
What this means in plain English is that pREG is likely a pointer to some sort of hardware index register, which in turn contains an address. To tell the compiler that this index register can get updated at any moment, the register itself should be treated as volatile.
A somewhat more readable way to write the same would be:
typedef void* volatile reg_add_t;
reg_add_t* pREG = (reg_add_t)0x20081004u;
Please note that the use of void* for this purpose is questionable. This register will have a defined use, possibly it should have been a uint32_t * volatile or uint8_t * volatile instead.

Related

How do I declare a static array with volatile elements?

Clarification about terminology used:
For static array I mean array statically memory allocated like: int x[10].
The problem
I need to declare a static array with volatile elements.
If I well understood how volatile qualifier works, it should be:
volatile uint8_t *x; // x is a pointer to volatile uint8_t
uint8_t *volatile x; // x is a volatile pointer to uint8_t
volatile uint8_t *volatile x; // x is a volatile pointer to volatile uint8_t
Ok, but now I need to do the same thing with a static array.
I tried with:
volatile uint8_t x[10]; // Only the pointer is decleared as volatile
uint8_t volatile x[10]; // Same as above
volatile uint8_t *x3[10]; // Casting problems and errors when I do ...
*x3[0] = 1; // ... something like this. Moreover, I do not know if this...
// ... statement declares the uint8_t element as volatile
Thanks!
UPDATE
Ok, as highlighted in the comments I should use:
volatile uint8_t x[10]
As I could understand, the problem is not in the declaration but in the usage of this variable in my code. I pass this element to a function whose prototype is:
static void functionName(uint8_t *buffer, uint32_t size);
I call the function in this way:
functionName(x, 10);
The compiler reports: passing argument 1 of 'functionName' discards 'volatile' qualifier from pointer target type
I can't change the function prototype, how can I solve the problem?
What you have to do to declare a static array of 10 volatile elements of type uint8_tis just:
volatile uint8_t x[10];
Be aware that this is a declaration of an array, which has nothing to see with pointers at this step.
Note: Later in your code, if you use x, it may decay to a pointer to the first volatile element, but in this case this pointer will have a constant value, given at the linking step. The pointed value is obviously volatile.
Stumbled across the problem myself today.
A variable CAN be 'sometimes' volatile.
Being volatile means, that its value can changed outside the program flow. By a parallel thread or an ISR.
Now if the ISR is what changes the value 'unexpectedly', it won't change unexpectedly inside the ISR itself. So for the ISR, the variable is not volatile and disabling compiler optimizations for it is counterproductive.
If I call a function from inside the ISR (and only from there), then the variable is not volatile and I don't want to pass a pointer to volatile, as it would produce inefficient code.
For this case, the solution I found was to have two declarations:
int a[x] = {};
volatile int * b = a;
Now the outside world uses b (globally declared in the header file) and treats the values pointed to by b as volatile, while the ISR (locally) defines both and uses a, treating the values as being not volatile.
Well, this is a very special case. In general, a function only sees the function parameter declaration. Which is either volatile or not, so the funciton will treat a parameter either always as being volatile or always as being not. It cannot automatically switch between two maybe completely differently compiled code blocks depending on the original volatile qualifier state of the passed parameter. Hence the warning.

Assign value of int variable to int pointer

I have the following C function used in an embedded software project. It's also used for the verification of the hardware and not in production.
void reg_read(int addr) {
int result;
int* reg_addr = (int*)(addr); // I cast the value of the addr variable to the reg_addr pointer hoping that it would point to the address stored in addr
result = (*reg_addr); // this should trigger a read transaction on the AXI interface of the ARM CPU that I'm simulating
}
// later on...in the main function
reg_read(0x08000704);
The embedded software runs in a simulated environment(using QEMU+SystemC) and I can see if the AXI read transaction happens or not. In this case it doesn't happen.
However, if I assign a constant value to the pointer like int* reg_addr = (int*)0x08000704; then the AXI transaction happens.
I assume the compiler generates different instructions in each case. I also tried to declare reg_addr as volatile int* reg_addr; but it didn't work either.
Is there a portable and compliant way of casting the value of an int variable to an int pointer?
Your question is:
Is there a portable and compliant way of casting the value of an int
variable to an int pointer?
There is not. Summed up from the comments:
Conversion of an integer to a pointer is implementation defined - Antti Haapala
It was suggested that you use uintptr_t or similar which is a good suggestion from Eugene Sh.
In the example of uintptr_t
uintptr_t = unsigned integer type capable of holding a pointer
From the vadefs.h file from the Microsoft Visual C++ header file vadefs.h it is defined as:
#ifdef _WIN64
typedef unsigned __int64 uintptr_t;
#else
typedef unsigned int uintptr_t;
#endif
In this manner, if you compile for x86 it would resolve to a 32bit data type and for x64, a 64 bit data type.

C - use of a volatile pointer

Why would one create a volatile pointer? And suppose I want a volatile pointer which points to a volatile variable, which of the following declarations would accomplish this:
volatile int *pData;
or
volatile int * volatile pData;
Why would one create a volatile pointer?
Example: To access data whose pointer is updated by a background process.
Stuff * volatile VideoFrame;
for (;;) {
Block_Changes();
Stuff MyCopy = *VideoFrame;
Allow_Changes();
Use(&MyCopy);
}
I want a volatile pointer which points to a volatile variable, which of the following declarations would accomplish this:
The 2nd meets the goal. volatile int * volatile pData; is a:
pData as volatile pointer to volatile int
The 1st volatile int *pData; is a non-volatile pointer to volatile data:
pData as pointer to volatile int
The volitle keyword is most often used in this context. # Eugene Sh.
One reason to use the modifier `volatile' is so the compiler does not optimize the variable out of existence.
Another reason to use the modifier 'volatile' is so when ever the code references that variable, it accesses the actual variable and not the value left in some register.
Another reason to use the modifier 'volatile' is when the variable value can change outside the control of the current program. For instance a hardware register or when an 'interrupt' updates the variable that your application is reading.

Macro with typecasting in C, Learning offsetof in detail

The following code and its output:
#include <stdio.h>
int x = 0;
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)x)->MEMBER)
#define offsetof_1(TYPE, MEMBER) ((size_t) &((TYPE *)1)->MEMBER)
#define offsetof_2(TYPE, MEMBER) ((size_t) &((TYPE *)2)->MEMBER)
#define offsetof_3(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
struct test{};
struct m {
int b;
char w;
struct test t;
int c;
};
int main(void) {
printf("Checking:%x\n",offsetof(struct m,b));
printf("Checking:%x\n",offsetof_1(struct m,b));
printf("Checking:%x\n",offsetof_2(struct m,b));
printf("Checking:%x\n",offsetof_3(struct m,b));
return 0;
}
Output:
Checking:0
Checking:1
Checking:2
Checking:0
I am trying to understanding the typecasting used here. I think, how compiler does is it treats (type *)(value) as that type starting at address (value). Hence for the given structure the expected value is 0,i.e. offsetof is b, but as we have used different values for typecasting we get different offset. Please let me know if my understanding is correct. I am just trying to understand how literals are typecasted and its implications. This is used in Linux kernel. Hence tagging them as well.
offsetof is a standard facility. The C standard defines it to behave a certain way, but does not define how the compiler implements it. Most compilers rely on undefined behavior, defining a special case for the sake of offsetof implementation.
What you have done is nonsense in terms of the language semantics. Treating the value 2 as a pointer is a classic example of undefined behavior.
It is not the design intent of the language that the user be able to define their own offsetof, so it is better not to try.
"Under the hood", yes pointers are typically scalars held in machine registers, and scalar arithmetic is used to obtain the address of a struct member. Performing the same arithmetic to get the address of an object at "location zero" yields its generic offset within any object. Using integers besides zero as locations may yield an arithmetic result or it may not. (It usually will but the idea is nonsense.)
Experimenting with programs that are conceptual nonsense is a risky way to discover how the system works, because you run the risk that it will flag an error or take a shortcut having detected that something is wrong.

Right syntax to make contents of an array volatile?

I vaguely remember that the order of the volatile keyword has influence on wether you want the pointer to the array to be volatile or the contents itself. If I want the content to be volatile, do I need to write:
volatile short Array[];
or
short volatile Array[3];
Either will do. It is the difference between
short volatile * ptr; /* pointer to volatile short */
and
short * volatile ptr; /* volatile pointer to short */
that matters.
const behaves the same way.
Both of them will work fine. Order of specifiers doesn't matter.
Read this answer for more detailed explanation.

Resources