Sometimes using pure-C libs in my C++ projects, I see strange (in my opinion) function declarations.
E.g.: libldap's 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 );
Why can't attrs[] be a const char *?
Declarations like this don't want to change the content of the pointer and generate a lot of issues:
// 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...
Is there any reason for not declaring such arguments as const?
This is mostly just (due to) a historical wart in the C standard that has never been fixed.
When const was added to C, the ability to implictly (and safely) convert simple pointers was added -- you can implicitly convert a T * to a const T * just fine. However, (safe) conversion of more complex pointer types was missed -- you can't convert a T * const * to a const T * const *. As a result, when a library takes a double pointer like this, it does not have any 'good' way of making it const if it is read only. Making it either a const char ** or a const char * const * would break some uses (requiring messy explicit casts).
Note that allowing implicit conversions of T ** to const T ** would be unsafe -- such a pointer could be used to modify a T * to point at a const T * without a cast.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With