在 c 中使用 const 关键字

Using const keyword in c

我一直在看源代码,我偶然发现了这段代码

    static char const *const delimit_method_string[] =
    {
        "none", "prepend", "separate", NULL
    };

我以为我知道 C 语言中 const 关键字的含义,但是看到这个语法后我感到困惑,因为我无法解码语法,所以我想知道像这样使用 const 的含义 我在互联网上搜索 我在 Whosebug 中看到了一些这样的问题,即

  1. Meaning of two const in C/C++ signature
  2. Double const declaration

但我仍然不明白该代码片段中语法的含义,可能是因为我对 C 的基础知识不够好,但我真的很喜欢改进它。

所以我写了一些代码来了解语法是如何工作的,这是我尝试过的:

    #include <stdio.h>
    
    int main()
    {
        char a = 'A';
        char b = 'B';
        char const * const ptr = &a;

        ptr = &b;

        printf("a is %c\n", *ptr);
        printf("a is %c", a);
    
        return 0;
    }

我得到了这个输出,有点符合我的预期。

$ gcc test.c
test.c: In function 'main':
test.c:9:13: error: assignment of read-only variable 'ptr'
    9 |         ptr = &b;
      |  

                    ^

我改了代码再测试,

    #include <stdio.h>
    
    int main()
    {
        char a = 'A';
        char b = 'B';
        char const const *ptr = &a;
    
        ptr = &b;

        printf("a is %c\n", *ptr);
        printf("a is %c", a);
    
        return 0;
    }

这次输出不是我预期的,

$ ./a.exe
a is B
a is A

如果有人能解释在 C 中使用 const 的正确方法以及第一个代码片段中的语法是如何工作的,我将非常感激。

char const const *ptr = &a;

这个双 const 没有任何特殊意义,因为它们都在 * 的同一侧。额外的 const 限定符被编译器忽略。可以这样写 char const const const const const*ptr = &a; 和 char const *ptr = &a; 是一样的这意味着:

pointer to constant character

如果我们把它改成

char const * const ptr = &a;

这意味着:

constant pointer to constant char

您的代码段将停止编译:https://godbolt.org/z/sM9qnv8fq

示例:

  • const int *ptr; - 指向常量整数的指针
  • int * const ptr; - 指向整数的常量指针
  • const int * const ptr; - 指向常量整数的常量指针

您的第一个示例 static char const *const delimit_method_string[] 声明:

static array of constant pointers to constant character

顺便说一句,我个人更喜欢在类型之前有第一个常量,即:

static const volatile char *const delimit_method_string[]

const char *p

这个声明

static char const *const delimit_method_string[] =
{
  "none", "prepend", "separate", NULL
};

声明一个数组,名称为 delimit_method_string 指向字符串文字的指针。

在 C 中,与 C++ 相反,字符串文字具有非常量字符数组类型。然而,您不能更改字符串文字。任何更改字符串文字的尝试都会导致未定义的行为。因此,最好通过以下方式声明指向字符串文字的指针,例如

const char *s = "Hello";

所以你可以像这样声明上面的数组

static char const * delimit_method_string[] =
{
  "none", "prepend", "separate", NULL
};

但是声明这个数组的程序员也想把at声明为常量数组。那就是他想让它的元素不能改变。

上面的声明你可以这样写

delimit_method_string[0] = "all";

要防止这种变化,数组的元素必须是常量。为此,您需要编写

static char const * const delimit_method_string[] =
{
  "none", "prepend", "separate", NULL
};

现在,由于第二个限定符 const,指针类型 const char * 的数组元素是常量。

Tom 更清楚地考虑以下声明。

char *p;

此声明声明了一个非常量指针,指向类型为 char 的非常量对象。

const char *p;

此声明声明了一个非常量指针,指向 char.

类型的常量对象
const char * const p;

这个声明声明了一个指向char.

类型常量对象的常量指针

最后的声明可以改写成

const char ( * const p );

至于这个你的声明

char const const *ptr = &a;

然后两个限定符中的一个 const 是多余的,因为它们都引用类型说明符 char.