c - 我一直看到 const char * const 参数,我知道第二个 const 对于堆栈副本毫无意义,那么他们



首先,让我声明我理解以下两者之间的区别:

const char *a;

char * const a;

const char * const a;

然而,最近我在用于将参数传递给函数时反复遇到后者,举个例子,Maxmind GeoLite2 mmdb C API 用于读取数据库文件,对每个指针参数使用以下格式:

const T * const 

例: https://github.com/maxmind/libmaxminddb/blob/master/include/maxminddb.h#L203

extern int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb);

我对 C/C++ 和 C/C++ 经常编译成的 x86 或 x86-64 有深入的了解,我知道指向文件名的指针和指向MMDB_s的指针都是堆栈分配的副本(或者在 x86-64 的情况下通过寄存器传递),那么使指针恒定的目的是什么?

我在这里错过了什么,还是他们不必要地用常量指针淹没了他们的 API,这些指针对使用它们的人真的没有最终影响?

C 标准明确指出,在函数原型声明中忽略顶级const限定符。 (N1570 §6.7.6.3p15,段落末尾括号中的句子。 这意味着,从代码试图调用MMDB_open的角度来看,声明

extern int MMDB_open(const char *const filename, uint32_t flags,
MMDB_s *const mmdb);

extern int MMDB_open(const char *filename, uint32_t flags,
MMDB_s *mmdb);

在语义上是相同的。 所以你认为这些限定符是不必要的是正确的。

但是,它们并非毫无意义,因为从功能实现的角度来看,它们是不一样的。 在MMDB的代码中,他们在某处有这个函数定义

int
MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb)
{
// code here
}

并且这个函数体中的代码不允许修改filenamemmdb变量(但允许通过mmdb写入并修改它指向的内容)。这就是为什么他们首先把限定符放在这些变量上的原因。

他们可能将限定符复制到公共头文件中的原型中,因为他们希望原型与函数定义完全匹配。 这使得维护头文件更容易。

最新更新