当我应该而且不应该在C中使用“const”时感到困惑

我有一个字典,如下所示:
typedef struct dictNode {
    int key;
    char *value;
    struct dictNode *next;
} Dict;

和get()函数是这样的:

char *get(const Dict *dict,int key) {
    if(!dict) return NULL;

    Dict *currPtr = dict;

    while(currPtr) {
        if(currPtr->key == key) {
            return currPtr->value;
        }

        currPtr = currPtr->next;
    }
}

编译此代码会产生以下错误:
dict.c:85:警告:初始化从指针目标类型中丢弃限定符

此警告涉及以下行:

Dict *currPtr = dict;

如果我在该行之前添加“const”,如下所示:

const Dict *currPtr = dict;

警告消失了……

1)我不明白的第一件事就是:我在get()中的dict参数中添加了“const”,这样编译器会在我尝试更改dict指向的地址时警告我,否则我将无法访问主程序中的字典导致我丢失了我指向的地址.现在,我正在创建一个新指针currPtr,它指向与dict相同的位置.这样,我使用这个指针来遍历字典并保持dict指针不变.为什么我还需要const为currPtr?

2)我不明白的第二件事是:线currPtr = currPtr-> next;正在改变currPtr指针,所以,如果我向currPtr添加一个const,为什么编译器不会警告我?

然后我有一个del()函数,如下所示:

Dict *del(const Dict *dict,int key) {
    if(!dict) return NULL;

    Dict *currPtr = dict;
    Dict *prevPtr = dict;

    while(currPtr) {
        if(currPtr->key == key) {
            prevPtr->next = currPtr->next;
            free(currPtr);
        }

        prevPtr = currPtr;
        currPtr = currPtr->next;
    }

    return dict;
}

请注意,我知道这个删除功能代码不完整,如果我想删除第一个元素,它就无法正常工作.没关系,我稍后会说完,这足以证明我的问题……

3)所以,在get()函数中我需要将const添加到currPtr但是在这个del()函数中,我不需要将const添加到currPtr或prevPtr?在这两个函数中,我正在更改currPtr指针,在del()函数的情况下,我也在更改prevPtr指针.为什么get()函数要求我在currPtr之前添加一个const,而del()函数不要求我在currPtr和prevPtr之前添加一个const?

我基本上可以恢复这个帖子:我的get()和del()函数的确切时间和地点应该使用const和为什么,以及何时何地我不应该?

解决方法

没有指针,你会有
const Dict currPtr

这是一个不变的Dict.现在,如果你把它作为你的指针

const Dict *currPtr

这是一个指向常量Dict的指针.这并不意味着指针是常量.但这确实意味着Dict指出被视为不变

currPtr->key = 10; // error,dict is treated as constant.

但指针不是

currPtr = otherPtr; // possible: the pointer is not constant

如果使指针保持不变,则第二种情况会出错.保持指向的dict也不变,这看起来像这样

const Dict * const currPtr = init;

现在你不能将currPtr设置为指向不同的东西,因为指针现在是常量,而不仅仅是指针所指向的那样.有些人喜欢看看const是否总是正确的东西,它使const.这看起来像这样

Dict const * const currPtr = init;

这与前一个片段相同.如果你从右到左阅读它,它会告诉你它是什么“const指向const Dict的指针”.如果您有类型,则无论您如何订购说明符

int const a = 10;
const int b = 10;

两者都是常数整数.这就是为什么我们可以把const放在Dict类型说明符的右边.

现在,如果你有一个指针,你总是可以假装你指向一个常量对象,即使该对象没有被声明为const.但是,如果您指向的是const对象,则不能假装使用非const对象:

int const *p = NULL;
// doesn't work without a cast. Will at least provoke a warning
int *pn = p;

int *p = NULL;
// always works: pretending to point to something const doesn't harm.
int const *pc = p;

请注意,如果将指针本身设为const,则规则与此不同.它们类似于应用于其他类型的const:

int const i = 0;
int j = i; // works. we only read the value of i. its const doesn't matter. 

int * const p = NULL;
int * q = p; // works: we only read the value of p (a null pointer).

将值复制到新变量(无论是否为指针)后,新变量不会以任何方式连接到另一个变量,因为读取的值与首先创建值的方式没有关联.另一个变量的const无关紧要.

相关文章

一.C语言中的static关键字 在C语言中,static可以用来修饰局...
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针...
浅谈C/C++中的指针和数组(一)指针是C/C++...
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时...
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下...
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面...