Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
数组的C数组:为什么我需要在这里强制转换为常量?_C_Arrays_Constants - Fatal编程技术网

数组的C数组:为什么我需要在这里强制转换为常量?

数组的C数组:为什么我需要在这里强制转换为常量?,c,arrays,constants,C,Arrays,Constants,为什么我需要将此代码中的print_args调用更改为print_args(argc,(const char**)argv),以使其可编译 #include <stdio.h> void print_args(int argc, const char *argv[]) { for (int i = 0; i < argc; ++ i) { puts(argv[i]); } } int main(int argc, char *argv[])

为什么我需要将此代码中的
print_args
调用更改为
print_args(argc,(const char**)argv)
,以使其可编译

#include <stdio.h>

void print_args(int argc, const char *argv[]) {
    for (int i = 0; i < argc; ++ i) {
        puts(argv[i]);
    }
}

int main(int argc, char *argv[]) {
    print_args(argc, argv);
    return 0;
}
(请注意,这只是一个简单的示例代码来说明问题。)

comp.lang.c常见问题解答,总结:

无法将
char**
值分配给
const char**
指针有点模糊。假设
const
限定符存在于 总之,编译器希望帮助您信守您的承诺 修改
const
值。这就是为什么可以将
char*
分配给
常量的原因
char*
,但不是相反:显然,“添加”是安全的
const
-指向一个简单指针,但使用它会很危险 在C中,如果必须分配或传递具有限定符的指针 除第一级间接寻址之外的不匹配,必须使用 显式强制转换

下面是它给出的示例,其中第3行应该给出警告:

const char c = 'x';         /* 1 */
char *p1;                   /* 2 */
const char **p2 = &p1;      /* 3 */
*p2 = &c;                   /* 4 */
*p1 = 'X';                  /* 5 */
第1行和第2行显然很好。在第4行,
&c
具有类型
指向常量字符的指针
,并且由于
char**
是类型
指向常量字符的指针
,那么
*p2
也是类型
指向常量字符的指针
,因此该语句没有问题。第5行也可以,因为
p1
是指向char的类型
指针,所以您可以修改它指向的内容

因此,如果第3行是正常的,那么您将完全按照您期望的
const
来执行,修改
指针指向const char
char
,因此第3行是不允许的,并且您不能在没有强制转换的情况下将
char**
分配给
const char**

请注意,使用强制转换只会隐藏问题,而不会解决问题。如果您添加了强制转换,那么上面的第3行就可以工作了,并且您可以间接地修改一个明显的
常量char
。虽然这并不总是正确的,但这是一个很好的例子,表明屈服于显然需要在C中强制转换通常只是一个错误


<>注意,在C++中,你可以声明你的函数参数<代码> const char * const *ARGV,它将不需要强制转换,并且防止间接修改。< /P>切线,对使用< <代码> -> Werror <代码>很有好处,但是你也应该考虑使用<代码> -Walth-Wu-PotoNoth< /COD>。它们可能会给你一些善意的错误,但即使是那些对你理解也有好处。
-Wextra
是的<代码>-pedantic
否,因为我使用GNU扩展(由
\ifdef\uu GNUC\uuu
保护)。您可以使用额外的
-Wno foo
选项关闭个别类型的警告。对于gnu扩展,我不确定具体的选项是什么,但可能类似于
-Wno gnu扩展
。您甚至可以使用右侧的
#pragma
s忽略特定行或块的警告。谢谢我必须在早上重新阅读这篇文章(在我睡觉后,当我可以再次集中注意力时)。
char*const*argv
在普通C语言中也能很好地工作。而且不需要演员阵容。这取决于你所说的“作品”是什么意思。它不需要强制转换,因为它不为
char
提供
const
属性<代码>常量字符c='c';常量字符*pc=&c;char*const*ppc=&pc,将
char**
传递给接受
char*const*argv
的函数将允许您执行
**argv='x'和类似的。我很困惑。常量修饰符的关联性是什么?因为添加
typedef char*str
然后使用
void print_args(int argc,const str argv[])
工作。我想说的是,
print_args
不会改变传递的
argv
的任何内容
argv
print\u args
中应该是完全不可变的。即使将其声明为
void print\u args(int argc,const str const*const argv)
也行得通,但我认为其中一个
const
是多余的。如果没有
typedef
,我就不能这样做吗?
const char c = 'x';         /* 1 */
char *p1;                   /* 2 */
const char **p2 = &p1;      /* 3 */
*p2 = &c;                   /* 4 */
*p1 = 'X';                  /* 5 */