I have a struct in C as follows:
typedef struct ENETPACKET_S {
unsigned n_rxcmd, n_txcmd;
uint64_t n_mac; // 8 bytes unsigned or 64 bit
unsigned n_rxmiss, n_rxerr, n_rxcrc, n_txcol;
} ENETPACKET;
A pointer is being defined from the variable of this struct here below:
static volatile ENETPACKET *const _net1 = ((ENETPACKET *)0x00500000);
I have two queries:
I understand pointers to a struct, but in the declaration of
_net1, a pointer from a variable/object of a struct is being defined. I don't get that.I am confused by the
((ENETPACKET *)0x00500000)initialization of theconstpointer, I don't understand what is being initialized here and the brackets and the*operator.
CodePudding user response:
It seems that you are working on an embedded device with possibly a micro-controller. In such systems, some peripherals can be configured/used by setting some registers. These registers can be read/written directly as it was memory available by your C program.
To give a small example of what it could looks like:
/* Control the PIN10 (input/output) */
/* The CONTROLLER of PIN10 is mapped at the address 0x00400000 */
static volatile uint8_t * const PIN10_CTRL = 0x00400000;
/* PIN10 control the output PIN of the MCU who is connected to a LED */
/* The STATUS of the PIN10 is mapped at the address 0x00400001 */
static volatile uint8_t * const PIN10 = 0x00400001;
*PIN10_CTRL = 0x1; /* Configure the PIN10 as a output PIN */
/* Blink the LED every second */
while (1)
{
*PIN10 = 1;
sleep(1);
*PIN10 = 0;
sleep(1);
}
If we consider your code now:
static volatile ENETPACKET *const _net1 = ((ENETPACKET *)0x00500000);
It seems like the networking interface of your micro-controller is putting the results of a ENETPACKET at the address 0x00500000. This address is fixed and can probably be found in the user manual of your micro-controller.
The structure is volatile to prevent the compiler to do any assumption on the binary code he will generate. If the keyword volatile was omitted, you could have some optimizations applied on the program and the data to be out-of-date.
This address 0x00500000 is probably the address of an array of N x ENETPACKET packets.
CodePudding user response:
For your first question (which is a bit unclear), maybe consider how pointers to simple objects are declared and initialized:
int i; // declares "i" as an "int"
int* p; // declares "p" as a "pointer to an int"
int* pi = &i; // declares "pi" as a pointer-to-int and initializes with address of "i"
Similarly, taking away the various qualifiers:
ENETPACKET str; // Declares "str" as an actual ENETPACKET structure
ENETPACKET *pstr = &str; // pstr is a pointer-to-structure set to address of "str"
Now, the const qualifier after the * (and before the name) means that your code cannot (must not) change the value (address) assigned to the _net1 variable in its initialization but that the actual data pointed to (i.e. the structure and the values of its members) can be changed: the pointer is const, not the referenced data; presumably, this is because the value assigned is a specific location in hardware.
For your second point, the (ENETPACKET*) preceding the constant is a cast operator; without it, your compiler will treat the 0x00500000 as an integer constant and generate a warning along the lines of the following (from clang-cl):
warning : incompatible integer to pointer conversion initializing 'volatile ENETPACKET *const' (aka 'volatile struct ENETPACKET_S *const') with an expression of type 'int' [-Wint-conversion]
Adding the explicit cast tells the compiler: "Yes, I know the types are not the same but I know what I'm doing and want you to treat them as compatible." Use casts with caution!
The second (external) parentheses are actually not required but have been added by the author for clarity (which is a good thing); they may become important if the value used is changed from a constant/literal (as it is currently) to a more complex expression involving pointer arithmetic, or in the (perhaps more likely) case that a macro is used in place of the fixed literal.
