繁体   English   中英

当用C中的指针定义时,为什么我们使用`const`作为字符串?

[英]Why do we use `const` for strings when defining with pointers in C?

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

我不明白为什么。 它是否正确? 字符串在C中是否真的具有常量值和变量指针?

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

一些困惑的程序员喜欢编写类似void func (int* const ptr)但在我看来,这只是混淆,因为ptr无论如何都是原始指针的副本,并且调用者不会关心函数的功能。它的本地副本在内部。

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

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

考虑以下:

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); )。 此表单主要用于传递引用字符串时,例如在命名实际对象时。

  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修改arrstr

  2. 当你使用

     char * const ptr; 

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM