C 只读指针到指针

C 只读指针到指针,c,pointers,C,Pointers,在C语言中,const char*p有时被称为“只读”指针:指向常量对象的指针(在本例中为char) 看来两者都是 const char**p const char*const*p 将是指向指针的只读指针的等效声明,具体取决于 但是,编译器(gcc、clang)会生成一个警告 我的问题:如何将指向指针(如char**p)的指针作为“只读”指针传递给函数,而不生成警告?如果需要显式强制转换,为什么在char**p而不是char*p的情况下 更多细节 这是一个具体的例子,说明我正在努力实现的目标 只

在C语言中,
const char*p
有时被称为“只读”指针:指向常量对象的指针(在本例中为
char

看来两者都是

  • const char**p
  • const char*const*p
  • 将是指向指针的只读指针的等效声明,具体取决于

    但是,编译器(gcc、clang)会生成一个警告

    我的问题:如何将指向指针(如
    char**p
    )的指针作为“只读”指针传递给函数,而不生成警告?如果需要显式强制转换,为什么在
    char**p
    而不是
    char*p
    的情况下

    更多细节 这是一个具体的例子,说明我正在努力实现的目标

    只读指针 此代码将
    char*ptr
    视为只读指针

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void readonly(const char *ptr)
    {
        // ... do something with ptr ...
    
        // but modifying the object it points to is forbidden
        // *ptr = 'j';  // error: read-only variable is not assignable
    }
    
    int main(void)
    {
        char *ptr =  malloc(12*sizeof(char));
        strcpy(ptr, "hello world");
    
        printf("before: %s\n", ptr);
        readonly(ptr);
        printf("after: %s\n", ptr);
    
        free(ptr);
        return 0;
    }
    
    clang编译器(版本6.0.0)给出了最具可读性的警告

    warning: passing 'char **' to parameter of type
        'const char *const *' discards qualifiers in nested pointer types
        [-Wincompatible-pointer-types-discards-qualifiers]
        readonly(ptr);
             ^~~
    note: passing argument to parameter 'ptr' here
        void readonly(const char *const *ptr)
    
    但gcc(8.1.1)也给出了警告

    旁白:当我试图添加限定符时,clang说传递
    char**
    会丢弃限定符,这似乎很奇怪

    问题
  • 如何将指向函数的指针(如
    char**p
    )作为“只读”指针传递给函数,而不生成警告

  • 如果需要显式强制转换,为什么在
    char**p
    而不是
    char*p
    的情况下


  • A我知道您想要声明指向指向const chat的指针的const指针与指向const char的指针类似。宣言是:

    void foo( const char ** const pointer )
    
    这有点“棘手”,因为星星从相反的方向计数

    让我们考虑一个非常简单的例子

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void foo( const char ** const pointer )
    {
        while(**pointer)
        {
            printf("%c", **pointer);
            (*pointer)++;
        }
        printf("\n");
    }
    
    void foo1( const char *const * pointer)
    {
        while(*pointer)
        {
            printf("%s\n", *pointer++);
        }
    }
    
    
    int main(void) 
    {
        char **pointer = malloc(sizeof(char *));
        char **pointer1 = malloc(sizeof(char *) * 4);
    
        char strings_in_RAM_0[] = "one";
        char strings_in_RAM_1[] = "two";
        char strings_in_RAM_2[] = "three";
    
        pointer1[0] = strings_in_RAM_0;
        pointer1[1] = strings_in_RAM_1;
        pointer1[2] = strings_in_RAM_2;
        pointer1[3] = NULL;
    
        *pointer = malloc(50);
    
        strcpy(*pointer,"Const pointer to pointer");
    
        foo(pointer);
        foo1(pointer1);
    
        free(*pointer);
        free(pointer);
        free(pointer1);
    
        return 0;
    }
    
    foo1
    函数参数的类型为指针指向常量指针指向常量字符


    您可以将代码简化为:

    char const ** var = (char**)0;
    
    第二个事实。这不是一个错误。以下是测试用例:

    我们再举一个例子:

    void foo( const char ** const pointer )
    {
        const char *ptr = *pointer;
        while(**pointer)
        {
            printf("%c", **pointer);
            (*pointer)++;
        }
        printf("\n");
        *pointer = ptr;
    }
    
    char const*****  c1 = (char*****)0; // fail
    char *const****  c2 = (char*****)0; // fail
    char **const***  c3 = (char*****)0; // fail
    char ***const**  c4 = (char*****)0; // fail
    char ****const*  c5 = (char*****)0; // ok
    char *****const  c6 = (char*****)0; // ok
    
    好。我们看到了模式


    我猜C/C++不能保证您可以修改深度大于2的任何内容,因为前面已经讨论过常量正确性的一些问题。

    在GCC中,您可以通过以下方式禁用代码中的警告:

    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
    readonly(ptr);
    #pragma GCC diagnostic pop
    

    我想clang也有类似的东西。至于你的第二个问题,注释中似乎有它。

    指向指针的等效只读指针是
    char*const*ptr
    “……有时被称为“只读”指针:…”——不被懂该语言的人所知。指针是可读写的。你完全错了。看看cdecl,检查一下你的课本。@melpomene它不是。指向指针的常量指针是
    常量字符**常量指针
    。指针星的计数方向相反-参见我的答案和example@PeterJ_01我不是说常数指针对指针。请看问题的第一句:我们正在讨论“指向常量对象的指针”,即指向指向char的const指针的指针。“常量对象”是指向char的指针。@melpomene但是您声明了指向常量指针的指针,而不是指向指针
    foo(指针)的常量指针是一个类型错误。从
    char**
    转换为
    const char**
    是不安全的;炭**pp;常量字符**ppc;pp=&p;ppc=pp*ppc=“foo”*p='x'这不仅仅是“另一个警告”;这是一个类型错误。C使它成为一个错误,因为它删除了
    const
    ,这是一件坏事。请不要建议人们忽略其程序中的类型错误。我的示例显示,从
    char**
    转换为
    const char**
    是不安全的,因为它允许您将
    const char*
    转换为
    char*
    ,这会自动去除
    const
    ,这是不安全的。您回答了一个问题。您提供了示例代码,说“它将给您一个警告,但它将按预期工作”。如果你不建议人们这样做,为什么还要张贴呢?
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
    readonly(ptr);
    #pragma GCC diagnostic pop