gpt4 book ai didi

当我应该和不应该在 C 中使用 "const"时感到困惑

转载 作者:太空狗 更新时间:2023-10-29 17:14:24 24 4
gpt4 key购买 nike

我有一本这样的字典:

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 指针完整。为什么我还需要为 currPtr 设置 const

2) 我不明白的第二件事是:currPtr = currPtr->next; 行正在更改 currPtr 指针,那么,如果我将 const 添加到 currPtr,为什么编译没有警告我?

然后我有一个像这样的 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 添加到 currPtrprevPtr 吗?在这两个函数中,我都更改了 currPtr 指针,对于 del() 函数,我也更改了 prevPtr 指针。为什么 get() 函数要求我在 currPtr 之前添加一个 constdel() 函数确实如此不需要我在 currPtrprevPtr 之前添加一个 const 吗?

我基本上可以将整篇文章恢复到:我应该在何时何地使用 get()del() 函数使用 const 以及为什么、何时何地我不应该这样做?

最佳答案

没有指针,你会

const Dict currPtr

这是一个常量字典。现在,如果你把它变成一个指针,你就有了

const Dict *currPtr

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

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

但是指针不是

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

如果您将指针设为常量,则第二种情况会出错。保持 pointed dict 不变,这看起来像这样

const Dict * const currPtr = init;

现在您不能将 currPtr 设置为指向不同的东西,因为指针现在是常量,而不仅仅是指针指向的内容被如此对待。有些人喜欢 const 总是对它使之成为 const 的东西正确的样子。这看起来像这样

Dict const * const currPtr = init;

这与前面的代码片段相同。如果您然后从右到左阅读它,它会告诉您它是什么“指向 const Dict 的 const 指针”。如果你有一个类型,那么你如何排列说明符并不重要

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

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

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

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 中使用 "const"时感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/710695/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com