我想制作一个宏,当给定类型 T 时,将返回一个指针类型,该指针类型在传递给函数时是只读的,如下所示:
void foo( readonly_ptr(char) str )
{
// can only read from str, not modify it
}
事实证明这比我想象的要难,因为仅仅在前面加上
const
是不够的。
我当前的代码是:
#define readonly_ptr(T) \
const typeof(T)*
适用于“简单”类型。
但不适用于所有类型。
当给定一个指向数组的指针类型(例如
int(*)[10]
)时,它会将其转换为 int(*const*)[10]
,这仍然允许函数像这样修改数组:
void foo( readonly_ptr(int(*)[10]) arr )
{
(**arr)[0] = 1;
}
类似地,对于指针类型(例如
char*
),它将其转换为 char *const*
,可以修改其底层 char
。
有没有办法制作一个保证只读参数的宏?
如果没有,是否有另一种方法可以确保函数不会修改参数,而不必每次都指定确切的类型。
我还尝试每次需要只读时总是传递
const void*
,但这仍然可以合法地转换为可修改类型。
C 声明语法,特别是关于指针的语法,对于如此简单的宏来说太丰富了。
正如您所发现的,它不适用于指向数组的指针、指向函数的指针,也不适用于指向指针的指针。
如果您将指针传递给数组,并且想要确保各个数组元素是常量,则必须以困难的方式做到这一点:
void foo( const T (*arr)[N] ); // or T const (*arr)[N]
我想如果您的根本问题是是否可以使内存位置在每种情况下都不可变,那么答案可能是否定的。我认为当指针与这样的 Makro 相关时,没有办法使某些内容成为 100% 只读。
这在 C 标准、编译器和系统之间可能有所不同,但放弃
const
并修改值应该是未定义的行为。查看此链接。有些系统可能只是出现段错误,如果您尝试通过强制转换来破解const
,其他系统可能会工作。所以这会很困难。
如果你想让这个指针恶作剧至少变得有些困难,那么创建一些 API 怎么样?您可以尝试传递一个函数,该函数在您调用
foo
之前定义的内存位置上进行读取。话又说回来,你可以直接复制然后传递它。