首先,让我声明我了解以下两者之间的区别:
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
}
并且该函数主体中的代码不允许修改
filename
和mmdb
变量(但允许通过mmdb
编写并修改其指向的内容)。这就是为什么他们首先将限定符放在这些变量上的原因。他们可能将限定符复制到公共头文件中的原型中,因为他们希望原型与功能定义完全匹配。这使得维护头文件更加容易。