
[英]Why do I use a star for pointers when printing chars but not strings in C?
[英]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);
)。 此表单主要用于传递引用字符串时,例如在命名实际对象时。
当您使用此声明时
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
的str
。
当你使用
char * const ptr;
这意味着ptr
不能指向除其初始地址之外的其他地址。 当您不打算在整个程序中更改指针地址时使用它,例如指向在嵌入式系统中查找表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.