C 常数和指针到指针
我对C 常数和指针到指针,c,pointers,constants,C,Pointers,Constants,我对const关键字感到非常困惑。我有一个函数接受字符串数组作为输入参数,还有一个函数接受可变数量的参数 void dtree_joinpaths(char* output_buffer, int count, ...); void dtree_joinpaths_a(char* output_buffer, int count, const char** paths); dtree\u joinpaths从参数列表构建字符串数组后,在内部调用dtree\u joinpaths\u a voi
const
关键字感到非常困惑。我有一个函数接受字符串数组作为输入参数,还有一个函数接受可变数量的参数
void dtree_joinpaths(char* output_buffer, int count, ...);
void dtree_joinpaths_a(char* output_buffer, int count, const char** paths);
dtree\u joinpaths
从参数列表构建字符串数组后,在内部调用dtree\u joinpaths\u a
void dtree_joinpaths(char* output_buffer, int count, ...) {
int i;
va_list arg_list;
va_start(arg_list, count);
char** paths = malloc(sizeof(char*) * count);
for (i=0; i < count; i++) {
paths[i] = va_arg(arg_list, char*);
}
va_end(arg_list);
dtree_joinpaths_a(output_buffer, count, paths);
}
当我更改char**path=malloc(count)时代码>到常量字符**路径=malloc(计数)代码>,此错误不再显示。我不明白的是
我认为指向地址的指针总是可以转换为常量指针,但不能反过来转换(在我看来,这就是这里发生的事情)
此示例适用于:
我做错了什么,或者我的误解在哪里
编辑
我的目的是使输入数据的内存对于函数是不可变的。(在本例中为路径
参数)。关键在于指针不是常量。要声明常量指针,请使用char*constptr
或声明指向常量指针的常量指针,char*const*const ptr代码>const char**ptr
是指向const char
的指针。实际上,如果有一个函数接受一个const char**并传递一个char**,这可能会导致出现问题,反之亦然
在您的特定情况下,您希望内存是不可变的,但它不是不可变的,并且可能随时发生变化。在多线程环境中,您希望该内存是线程安全的,并且只要它位于堆栈或堆中,就不需要互斥来访问它
所有这些都是为了避免错误,但是如果您确信这不会导致错误,您可以简单地将指针转换为const char**。您不能将char**
传递到const char**
中,因为编译器无法保证const char**
的正确性
假设您有以下代码(并编译):
有关没有函数调用的相同示例,请参见。原因char**
->const char**
是“危险”转换,如下代码:
const char immutable[] = "don't modify this";
void get_immutable_str(const char **p) {
*p = immutable;
return;
}
int main() {
char *ptr;
get_immutable_str(&ptr); // <--- here is the dangerous conversion
ptr[0] = 0;
}
const char immutable[]=“不修改此项”;
void get_immutable_str(常量字符**p){
*p=不可变;
返回;
}
int main(){
char*ptr;
get_immutable_str(&ptr);//const char**
不是该模式的示例,因为如果t
是char*
那么const t
是char*const
,而不是const char*
(在这一点上,可能不值得再写左边的const
:写char-const*
,您不会期望它与t-const
相同,其中t是char*
)
您可以安全地将char**
转换为char*const*
,并且(出于需要的原因,不仅仅是简单规则)您可以安全地将char**
转换为char const*const*
您试图将T**
转换为const T**
,而不是T*
转换为const T*
@melpomene:我看不出区别。不,第一个是指向T的指针,第二个是指向const T的指针,第二个是指向const T的指针rd一是指向T的指针,第四个是指向常量T的指针。没有一个指针是常量。@RamyAlZuhouriconst char**ptr
,很抱歉把它弄糊涂了。但是,指针仍然不会是常量。Wuh,很抱歉我的措辞不好。我的意图是使函数体的内存不可变,因此,const char**ptr
应该可以,如果它使char
常量,对吗?@NiklasR是的,是的。顺便说一句,你可以检查如下内容:-)谢谢。但是,我仍然不明白为什么我不能传递char**ptr
(这是指向可变字符的可变指针),指向需要常量字符**ptr
的函数(它是指向不可变字符的可变指针的可变指针).难道这条规则不适用吗,可以一直将可重复的对象视为不可变的,但不能反过来处理吗?@NiklasR,因为这不是你正在做的。你试图将t**
转换为const t**
,而不是t*
转换为const t*
。为什么内存不是不可变的(当然,在编译时,我知道内存不能在运行时保持不变)当用const
标记它时,我想知道为什么编译器告诉我这些类型是不兼容的,而不仅仅是“因为它们是”@melpomene说,将T*
转换为const T*
和将T**
转换为const T**
是有区别的,但是为什么呢?谢谢。运行时可能也有一些不可变的内存,例如const char*str=“hello”,这是不可变内存,如果你试图更改它,就会出现分段错误。“实际上,如果有一个函数接受常量字符**,而您传递了一个字符**,这可能会导致出现问题,反之亦然。”。"-只有相反的部分是正确的。不尝试变异可变的东西是好的,尝试变异不可变的东西不是。可能会产生问题的一件事是假设这个内存真的是不可变的,当它改变时会得到坏的惊喜。@H2CO3:这正是我的假设,这就是为什么我不理解为什么icit casting会触发一条错误消息:(@SteveJessop-你能详细解释一下最后一句话吗(原因不仅仅是简单的规则)?
void foo(const char **ppc, const char* pc)
{
*ppc = pc; // Assign const char* to const char*
}
void bar()
{
const char c = 'x';
char* pc;
foo(&pc, &c); // Illegal; converting const char* to const char**. Will set p == &c
*pc = 'X'; // Ooops! That changed c.
}
const char immutable[] = "don't modify this";
void get_immutable_str(const char **p) {
*p = immutable;
return;
}
int main() {
char *ptr;
get_immutable_str(&ptr); // <--- here is the dangerous conversion
ptr[0] = 0;
}