【问题标题】:Why do some libs use non-const char * as function argument?为什么有些库使用非常量 char * 作为函数参数?
【发布时间】:2021-05-31 16:50:32
【问题描述】:

有时在我的 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[] 不能是 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++(在同一问题中同时使用CC++ 标签的罕见情况。)
  • OpenLDAP 是一个非常古老的、成熟的库。它是在const-正确性不是事实上的要求的日子里写的。在这种情况下,它应该是一个const指针。
  • char *attrs[]char **attrs 本质上是一样的,而const char** 的行为并不像您直观预期的那样,因此它可能与此有关。
  • Fwiw,const d = {"blabla", "blablu"}; 无论如何都不会工作(是的,我禁用了隐式整数)。无论如何,在远程现代代码中,当指向的数据被认为是不可变的时,有 zero 理由不正确地对 any 类型的指针进行常量化。
  • 顺便说一句,func({"blabla"}); 不是纯 C,因为你需要一个复合文字。

标签: c++ c libs


【解决方案1】:

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

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

请注意,允许将 T ** 隐式转换为 const T ** 是不安全的——这样的指针可用于修改 T * 以指向 const T * 而无需强制转换。

【讨论】:

    【解决方案2】:

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

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

    在处理诸如此类您知道不会修改参数的库时,您必须应用 const_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);
    

    【讨论】:

    • 谢谢,当然。我一直使用这个解决方案,我的问题更多是关于 libs 开发人员的原因。我也在 STM 库中看到过,总是将其解释为代码质量低下。
    猜你喜欢
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2021-02-05
    • 1970-01-01
    • 2019-04-21
    • 2016-04-06
    相关资源
    最近更新 更多