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

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),那么使指针成为const有什么目的?

我是否在这里遗漏了一些东西,还是它们不必要地用const指针充斥了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编写并修改其指向的内容)。这就是为什么他们首先将限定符放在这些变量上的原因。

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

09-29 21:56