结构指针及其初始化

Struct pointers and their initialization

我在 C 中有一个结构如下:

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;

正在从下面这个结构的变量定义一个指针:

 static volatile ENETPACKET *const _net1 = ((ENETPACKET *)0x00500000);

我有两个问题:

  1. 我理解指向结构的指针,但在 _net1 的声明中,定义了来自结构 variable/object 的指针。我不明白。

  2. 我对const指针的((ENETPACKET *)0x00500000)初始化感到困惑,我不明白这里初始化的是什么以及括号和*运算符。

看来您正在使用可能带有微控制器的嵌入式设备。在这样的系统中,一些外设可以通过设置一些寄存器来configured/used。这些寄存器可以直接 read/written 因为它是 C 程序可用的内存。

举一个小例子来说明它的样子:

/* 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);
}

如果我们现在考虑您的代码:

static volatile ENETPACKET *const _net1 = ((ENETPACKET *)0x00500000);

似乎 你的微控制器的网络接口把 ENETPACKET 的结果放在地址 0x00500000 上。这个地址是固定的,可能可以在你的微控制器的用户手册中找到。

结构是volatile以防止编译器对他将生成的二进制代码做任何假设。如果关键字 volatile 被省略,您可能会对程序应用一些优化,并且数据会过时。

这个地址0x00500000可能是N x ENETPACKET个数据包数组的地址。

对于你的第一个问题(有点不清楚),可以考虑如何声明和初始化指向简单对象的指针:

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"

同样,去掉各种限定符:

ENETPACKET str; // Declares "str" as an actual ENETPACKET structure
ENETPACKET *pstr = &str; // pstr is a pointer-to-structure set to address of "str"

现在,const 限定符 * 之后(以及 名称之前)意味着您的代码不能(不得)在其初始化时更改分配给 _net1 变量的值(地址),但指向的实际数据(即结构及其成员的值)可以被改变:指针是const,不是引用的数据;据推测,这是因为分配的值是硬件中的特定位置。

对于你的第二点,常量前面的(ENETPACKET*)是一个cast operator;没有它,您的编译器会将 0x00500000 视为 整数 常量并生成如下警告(来自 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]

添加 explicit cast 告诉编译器:“是的,我知道类型不一样,但我知道我在做什么,希望你将它们视为兼容”谨慎使用强制转换!

第二个(外部)括号实际上不是必需的,但作者为了清楚起见添加了(这是一件好事);它们 可能 如果使用的值从 constant/literal (目前)更改为涉及指针算术的更复杂的表达式,或者在(可能更有可能)使用宏代替固定文字的情况。