为了定义带有指针的数组,我们编写
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++。
-
使用此语句时
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
中的字符串。 -
当您使用
char * const ptr;
这意味着
ptr
不能指向初始地址以外的其他地址。当您不打算在整个程序中更改指针地址时,例如指向嵌入式系统中的查找表,则使用它。