为什么我们在 C 中使用指针定义字符串时使用 'const'?



为了定义带有指针的数组,我们编写
int *const a;
因为数组具有变量值但具有常量指针。 但是对于字符串,我们写
const char *s;.

我不明白为什么。这是对的吗?字符串在 C 中真的有常量值和变量指针吗?

请考虑以下事项:

char* a;
char* const b = "Hello"
const char* c;
const char* const d = "world";

a只是指向一个角色。这可能是字符串的第一个字符,也可能是单个字节。可以通过写入*a='Z'a[0]='q'或通过a传递给采用char*参数的函数来修改该字符。指针本身也可以修改为指向其他一些字符,例如a=b;a="foo";.这是最灵活的形式,也是最不安全的形式,因为你可以用它做任何事情。

b是指向字符的常量指针。在本例中,它指向一个字符数组。这些字符可以修改,例如b[1]='a';*b=0;b本身是恒定的,这意味着它永远不会指向内存的不同部分。当您分配了要修改其内容的缓冲区或数组,但由于它是由操作系统分配的,因此无法移动时,可以使用此表单。

c指向一个恒定的字符。您可以更改它指向的内容(c="foo";c=b;(,但不能使用此指针更改它指向的字符 -即使它指向非常量缓冲区b。此形式通常在处理预生成的字符串时使用。您可以使用此变量来存储找到的字符串,并传递它们的地址,只要您不更改字符串本身即可。

d是指向常量字符的常量指针。您无法更改指针指向的字符,也不能将指针本身指向其他内存位置。您所能做的就是读取字符串或单个字符(char e=d[4];puts(d);(。这种形式主要用于传递引用字符串时,例如在命名真实对象时。

int *const a;这样的代码在大多数用例中都是无稽之谈。使指针const的主要用途是当您有一个基于指针的查找表时。或者,当您希望将指针存储在嵌入式系统的只读内存中时。

一些困惑的程序员喜欢像void func (int* const ptr)一样编写代码,但在我看来,这只是混淆,因为无论如何ptr是原始指针的副本,调用者不会关心函数在内部对其本地副本做什么。

不要与常量正确性混淆,这意味着指向只读数据的指针应声明为const int* ptr。这被广泛认为是良好的编程实践,并且它是规范的C,因为大多数C标准都利用了C标准库的const正确性。

至于指向字符串文字(如"hello"(的指针,它们应该声明为const char* ptr = "hello";,因为修改字符串文字会调用未定义的行为。这意味着修改它是一个错误,可能会导致程序崩溃。这是 C 中的一个已知缺陷 - 字符串文字本身的类型,即使我们不允许写入它,也是char[]。这是出于历史原因。但是,在C++中,他们已经修复了从 C 继承的这个语言缺陷,因此所有字符串文字都const char[]C++。

  1. 使用此语句时

    char *str = "Stack Overflow";
    

    这意味着str指向字符串"Stack Overflow",它存储在代码内存中,不允许用户修改它。因此,对于此语句,在char *str之前编写const没有任何效果,因为字符串已经是常量。

    但是当你指向数组的基址时,const起着重要作用,比如

    char arr[20];
    strcpy(arr,"Stack Overflow");
    const char *str = arr;
    

    使用const意味着您无法通过指针str修改arr中的字符串。

  2. 当您使用

    char * const ptr;
    

    这意味着ptr不能指向初始地址以外的其他地址。当您不打算在整个程序中更改指针地址时,例如指向嵌入式系统中的查找表,则使用它。

最新更新