C 确保返回的指针为常量,而不引发警告
我的目标是为我的库定义一个干净的API。C 确保返回的指针为常量,而不引发警告,c,constants,compiler-warnings,rvalue,function-declaration,C,Constants,Compiler Warnings,Rvalue,Function Declaration,我的目标是为我的库定义一个干净的API。 我的一个函数返回一个指针,该指针不能用指针算术修改。 为了在编译时做到这一点,我计划在函数原型中使用const关键字 下面是一个天真的例子: int global_var = 12; int* const access_global_var(){ return &global_var;} int main(void) { int* const ptr = access_global_var(); *ptr = 15; //<
我的一个函数返回一个指针,该指针不能用指针算术修改。
为了在编译时做到这一点,我计划在函数原型中使用
const
关键字
下面是一个天真的例子:
int global_var = 12;
int* const access_global_var(){ return &global_var;}
int main(void) {
int* const ptr = access_global_var();
*ptr = 15; //< Should be valid
ptr++; //< Should be Invalid
return 0;
}
这个警告正确吗?有什么我遗漏的吗?有没有更好的方法来实现我的目标?由于警告在我的项目中被视为错误,正如您所料,这是有问题的。
感谢函数的返回类型
int* const access_global_var(){ return &global_var;}
没有道理
如果您在任何情况下都要删除限定符const,那么您可以不编写
++access_global_var();
因为函数返回一个右值
但即使你有限定符const,你也可以写
int *p = access_global_var();
然后
++p;
也就是说,您可以为非常量对象指定一个常量值
因此,编译器警告说,返回类型中使用的限定符没有意义,可以在不更改逻辑的情况下删除。如果出于某种原因,您真的想强制开发人员这样做(如果他们愿意,他们将很容易绕过此限制),您始终可以使用类似宏的函数来强制执行此操作。如果希望宏特定于特定的全局变量,如示例中所示,它可能如下所示:
#define create_global_var_accessor(ACCESSOR) \
int *const ACCESSOR = &global_var
int global_var = 12;
int main(void) {
create_global_var_accessor(ptr);
*ptr = 15; //< Should be valid
ptr++; //< Should be Invalid
return 0;
}
除此之外,我将附和莫斯科的Vlad说,我认为这不是一个需要解决的问题。您不需要限定返回值。您分配返回值的变量是您需要限定的地方。我同意我不需要它。但是有没有一种方法可以强制用户使用const及其变量?即使您可以强制调用方只将函数值分配给
const
,实际上需要int*const x=access_global_var()代码>,则调用方可以执行int*y=x代码>。想象一下,如果函数返回的是一个简单的int
,而不是指针,您会问什么。坚持调用者只能给constintx=3分配一个返回值,比如3,有什么用代码>并且永远不允许将自己的x
用于任何其他用途?他们必须能够在表达式中使用x
,是吗?说x+4
?这也不应该是常数,对吗?……假设你可以强制一个常数x=3代码>并以某种方式传播此消息以禁止inty=x代码>。但是,如果x+4
也没有被强制为const
,那么他们可以写入x+0
来删除const
,从而执行int y=x+0代码>。或者,如果你不允许,那么inty=x+4-4代码>。类似地,指针可以是int*x=access\u global\u var()+1-1代码>。或者int*x=access\u global\u var+HardToEvaluateFunction()代码>,这将阻止编译器知道函数返回零。从语言设计的角度来看,这个要求是不可行的。我理解左值。事实上,您可以编写int*p=access\u global\u var()
是我要解决的问题。@gberth为什么是问题?为什么用户不能增加指针?他不会通过增加指针来更改全局变量。
#define create_global_var_accessor(TYPE, ACCESSOR, ACCESSEE) \
TYPE *const ACCESSOR = &(ACCESSEE)
int global_var = 12;
int main(void) {
create_global_var_accessor(int, ptr, global_var);
*ptr = 15; //< Should be valid
ptr++; //< Should be Invalid
return 0;
}