Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.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_Pointers_Constants - Fatal编程技术网

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的指针。没有一个指针是常量。@RamyAlZuhouri
    const 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;
    }