我想做一个宏,当给定一个类型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.

有没有办法制作一个保证只读参数的宏?

如果不是,有没有其他方法可以确保函数不会修改参数,而不必每次都指定确切的类型.

我还try 在每次需要只读类型时总是超过const void*,然而,这仍然是合法的-可以转换为可修改的类型.

推荐答案

我想如果你的基本问题是是否有可能使内存位置在任何情况下都是不可变的,答案可能是否定的.

  • 如果没有,有没有其他方法可以确保函数不会修改参数,而不必每次都指定确切的类型?

这在C标准、编译器和系统之间可能有所不同,但丢弃const并修改值应该是未定义的行为.看看这个link.有些系统可能只是分段错误,其他系统可能会工作,如果你试图破解const左右的施法.因此,这将是困难的.

如果您想让这个指针恶作剧变得至少有些困难,那么创建一些API怎么样?您可以try 传递一个函数,该函数在调用foo之前定义的内存位置上执行读取.再说一次,你可以直接复制,然后通过.

C++相关问答推荐

什么C代码将确定打开的套接字正在使用的网络适配器?

由Go调用E.C.引起的内存快速增长

创建一个fork导致fget无限地重新读取文件

GLIBC:如何告诉可执行文件链接到特定版本的GLIBC

我怎么才能用GCC编译一个c库,让它包含另一个库呢?

是否可以通过调用两个函数来初始化2D数组?示例:ARRAY[STARTING_ROWS()][STARTING_COLUMNS()]

FRIDA-服务器成为端口扫描的目标?

如何按顺序将所有CSV文件数据读入 struct 数组?

在for循环中指向数组开头之前

C:在编译时构建和使用字符串文字的预处理器宏?

当内存来自Malloc时,将char*转换为另一个指针类型是否违反了严格的别名规则?

如何在双向表中实现线程安全,每个条目仅使用4位,同时避免任何全局锁?

Printf()在C中打印终止字符之后的字符,我该如何解决这个问题?

GetText不适用于包含国际字符的帐户名称

为什么二进制文件的大小不会随着静态数据的大小而增加?

在C中使用无符号整数模拟有符号整数

C编译和运行

为什么 Linux 共享库 .so 在内存中可能比在磁盘上大?

Makefile - 将 .o 文件放入子文件夹中

用于内存布局的size命令(文本、数据、bss)