为什么有些库使用非常量char*作为函数参数?

有时在我的 C++ 项目中使用纯 C 库,我会看到奇怪的(在我看来)函数声明。

例如:libldap 的ldap_search_ext():https ://linux.die.net/man/3/ldap_search_ext_s

int ldap_search_ext(
       LDAP *ld,
       char *base,
       int scope,
       char *filter,
       char *attrs[], // this one!
       int attrsonly,
       LDAPControl **serverctrls,
       LDAPControl **clientctrls,
       struct timeval *timeout,
       int sizelimit,
       int *msgidp );

为什么 attrs[] 不能是 a const char *

像这样的声明不想改变指针的内容并产生很多问题:

// pure C
void func(char * data[])
{
  ...
}

func({"blabla"}); // won't work (corrected: yes, this is wrong syntax, but it's true for structs of pointers)

const char *d[] = {"blabla", "blablu"};
func(d); // won't work

// C++
const std::string str("blabla");
char * data[] = { str.data() }; // even non-const won't work (because data() returns const*)
/// etc...

是否有任何理由不将此类参数声明为 const?

回答

这主要是(由于)C 标准中从未修复的历史问题。

const被添加到 C 时,添加了隐式(和安全)转换简单指针的能力——你可以隐式地将 a 转换T *为 aconst T *就好了。然而,更复杂的指针类型的(安全)转换被遗漏了——你不能将 a 转换T * const *为 a const T * const *。结果,当一个库采用这样的双指针时,const如果它是只读的,它就没有任何“好”的方法来制作它。使其成为 aconst char **或 aconst char * const *会破坏某些用途(需要凌乱的显式强制转换)。

请注意,允许T **to 的隐式转换const T **是不安全的——这样的指针可用于修改 aT *指向 aconst T *而不进行强制转换。


回答

一个可能的原因是 C 中的字符串常量(与 C++ 不同)不是const.

因此,许多本应存在的库在历史上缺乏常量正确性。如果字符串常量是const,程序员将不得不考虑它。

在处理诸如此类的库时,您知道不会修改参数,您必须应用 aconst_cast使其适合。

char *d[] = {const_cast<char *>("blabla"), const_cast<char *>("blablu")};
func(d);

const std::string str("blabla");
char * data[] = { const_cast<char *>(str.data()) };
func(data);


以上是为什么有些库使用非常量char*作为函数参数?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>