emb*_*guy 3 c embedded const-correctness
我一直在研究一些类似于以下内容的代码:
typedef struct
{
unsigned char x;
unsigned short y;
unsigned char[NUM_DEFINED_ELSEWHERE];
} My_Struct;
static My_Struct my_useful_struct; // Variables initialized elsewhere in code.
void myFunction(const My_Struct * p_my_struct)
{
/* Performs various read-only actions utilizing p_my_struct. */
}
void myOtherFunction(void)
{
static My_Struct * p_struct = &my_useful_struct;
myFunction(p_struct);
}
Run Code Online (Sandbox Code Playgroud)
我的代码编译没有任何问题,但在审查时我被告知,除非我对 p_struct 进行类型转换,否则这可能会导致在某些平台(即 8051)上出现未定义的行为。然而,我什至从未收到过有关编译器的警告。 在将指针传递给函数时不进行类型转换(const My_Struct *)是否会导致未定义的行为?
我使用指向的指针声明上述函数的原因const是因为我希望能够处理指向 const 的指针和指针。 在上述情况下不进行类型转换是一种不好的编码习惯吗?
感谢您的帮助!
这绝对没问题;My_Struct *编译器执行从到 的隐式转换const My_Struct *。C99 规范的 §6.3.2.3 规定:
对于任何限定符q ,指向非q限定类型的指针可以转换为指向该类型的q限定版本的指针;原始指针和转换后指针中存储的值应相等。
此外,即使您使用两个不一致的声明来声明该函数,这样一个文件也会看到它的声明如下:
void myFunction(My_Struct * p_my_struct);
Run Code Online (Sandbox Code Playgroud)
即使它实际上是这样定义的:
void myFunction(const My_Struct * p_my_struct) { ... }
Run Code Online (Sandbox Code Playgroud)
即使这是规范所允许的,即使编译器不知道执行隐式转换,因为My_Struct *和const My_Struct *具有相同的表示形式(因此无论如何,转换都是无操作的)。
(感谢 Christoph 和 awoodland 的评论澄清了后一种情况。在这个答案的先前版本中,我错误地声称这是未定义的行为。)
编辑添加:出于同样的原因,也允许使用带有指向非常量参数的指针的声明来定义函数,但使用带有指向常量参数的声明来调用它。但尝试实际修改数据很可能会导致未定义的行为,具体取决于数据的来源。(char *例如,A 可以初始化一个字符串常量,但尝试修改该常量中的数据是未定义的行为。)