为什么这允许从(char *)转换为(const char *)进行提升?

4
考虑到scanf在Microsoft文档中有(const char *),以及对此问题的回答,如果我将(char **)提升为(const char **),会发生什么?基本上为什么这会编译?
#include <stdio.h>
int main(int argc, char **argv)
{   
    char szArray[50];
    int  i = 0;
    strcpy(szArray,"10");
    /* the following code is upcasting the (char *) to (const char *) */
    sscanf(szArray,"%d",&i);
    return 0;  
}

为什么这个无法编译?

#include <stdio.h>
void processargs(const char **p)
{ 
}
int main(int argc, char **argv)
{
    processargs(argv);          
    return 0;  
}

两者似乎对指针做了相同的事情!


1
你不明白一件事:如果 T -> U 可行,并不意味着 T* -> U* 也可行。一个简单的例子:double a = 4; /* int -> double / int p; double dp = &p; / int -> double* ?? */ - Johannes Schaub - litb
我这里不会改变类型... 两个集合都是指针。 - ojblass
请关闭另一个而不是这个... - ojblass
星号的数量很重要。仔细查看 Palecek 在您之前的问题中的答案。 - dmckee --- ex-moderator kitten
4个回答

12

char** -> const char ** 是危险的,因为你可能会意外修改底层的 const 对象。

正确的写法是:

void processargs(const char * const *p)
{ 
}

3
可以宣传一下你可以这样使用const。我认为很多人都不知道这一点。 - Dana the Sane

3

您可以增加访问限制,但不能减少它。从普通指针到常量指针是可以的,从常量指针到普通指针则不行。

第二个例子无法编译,因为您并没有将指针转换为常量指针,而是将一个类型(char*)的指针转换为另一种类型(const char*)的指针。例如,您可以将char**更改为char* const*,但不能将const char**更改为char**


为什么第二个例子无法编译呢? - ojblass

2
请看下面内容是否能为您澄清疑惑:

请检查以下内容:

char * a_mutable = /*...*/;
const char * a_constant = /*...*/;

char **pointer_to_mutable = &a_mutable;   /* ok */

const char **pointer_to_constant = &a_constant;   /* ok */

pointer_to_constant = pointer_to_mutable;   /* oops, are you sure? */

*pointer_to_constant = a_mutable;   /* valid, but will screw things around */

最后一行是有效的,因为pointer_to_constant是一个可变指向常量字符的可变指针,但这会破坏事情,因为您正在使a_constant指向a_mutable。这就是为什么不允许pointer_to_constant接收pointer_to_mutable的内容。

0
你的第一个例子是可以工作的,因为你将 char*rvalues 转换为 const char*,这是可以的(基本上是因为你不能对 rvalues 进行赋值)。第二个例子不行,因为(非 const)指针的目标始终是 lvalue。
尝试一下(也许借助编译器),看看你可以对 char** 做哪些操作,哪些操作适用于 const char**,并思考哪些类型是可互换的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接