C语言const修饰指针、宏表达式解析及DaVinci生成代码赋值问题咨询
C代码问题解答
问题1:Expr1表达式与多const关键字含义
你的理解存在部分错误,具体拆解如下:
- 这行
extern const struct s2 * const p3;是合法的全局变量声明,并非“未声明”。extern表示该变量的定义在其他编译单元(即DaVinci生成的其他.c文件中),编译阶段会留空地址位,链接阶段会绑定到实际定义的地址。 - 多个
const的含义按照C语言右左法则解析:从变量名p3出发从右往左读:- 靠近p3的
const修饰指针本身,说明p3是常量指针,本身的指向不可修改,不能写p3 = xxx这类代码 - 靠近
struct s2的const修饰指针指向的对象,说明p3指向的s2结构体是只读的,常规写法下不能通过p3修改s2结构体的成员值
完整含义为:声明一个具有外部链接属性的常量指针p3,该指针指向只读的struct s2类型对象。
- 靠近p3的
问题2:Expr2宏定义的运算逻辑拆解
#define untilp1() (*(&p3->p1))的运算顺序按照C运算符优先级(-> > & > *)逐层拆解:
- 第一步执行
p3->p1:优先通过p3访问其指向的s2结构体的p1成员,p1本身是s1*类型的指针 - 第二步执行
&(p3->p1):取s2结构体中p1这个成员自身的内存地址,得到类型为s1**的二级指针 - 第三步执行
*(&p3->p1):对二级指针解引用,得到的就是s2的成员p1本身,效果和直接写p3->p1完全等价
这个写法的作用是绕开编译器的const检查:因为p3指向的是const struct s2,直接写p3->p1 = xxx会触发编译器的只读修改报错,通过取地址再解引用的操作可以绕过类型检查,给p1赋值。
宏替换后你写的untilp1()->v1 = v2完全等价于p3->p1->v1 = v2。
问题3:DaVinci场景下赋值可行性说明
DaVinci生成的是面向嵌入式MCU的AUTOSAR代码,这类场景默认禁用动态内存分配(malloc),所有内存都是静态分配或者映射到固定物理地址的,你看不到malloc是正常情况。
你当前运行失败的核心原因是p3->p1没有指向合法的可写s1类型内存区域,只要满足以下两个条件就可以正常赋值:
- p3本身的指向有效:因为是DaVinci生成的全局变量,默认已经绑定了合法的地址,不会是空指针
- 你需要先给
p3->p1赋值一个合法的可写内存地址:比如你可以自己定义一个全局的s1变量,先通过宏给p1赋值,再修改v1,示例代码如下:
// main.c新增代码 static s1 my_s1; // 静态分配s1类型内存,在RAM区可写 int main() { int v2 = 10; untilp1() = &my_s1; // 先给p1赋值合法地址 untilp1()->v1 = v2; // 此时运行不会失败 return 0; }
如果p1指向的是外设寄存器地址,只需要确认该寄存器是可写的,也可以直接赋值。
内容的提问来源于stack exchange,提问作者Trilokinath Modi
相关产品推荐
相关产品推荐

