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

时间:2022-05-31 22:29:47

I heard from a C developer that for defining arrays with pointers, we write
int *const a;
because arrays have variable values but constant pointers. But for strings, we write
const char *s;.

我从一位C开发人员那里听说,为了用指针定义数组,我们编写int * const a;因为数组具有变量值但是常量指针。但对于字符串,我们编写const char * s;。

I didn't understand why. Is this correct? Do strings really have constant values and variable pointers in C?

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

3 个解决方案

#1


4  

Code such as int *const a; is nonsense in most use-cases. The main use of making a pointer const is when you have a pointer-based look-up table. Or when you want a pointer to be stored in read-only memory on an embedded system.

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

Some confused programmers like to write code like void func (int* const ptr) but this is only obfuscation, in my opinion, since ptr is a copy of the original pointer anyhow, and the caller couldn't care less what the function does with its local copy internally.

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

Not to be mixed up with const correctness, which means that pointers to read-only data should be declared as const int* ptr. This is widely recognized as good programming practice, and it is canonical C, since most of the C standard utilizes const correctness for the C standard library.

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

As for pointers to string literals (like "hello") specifically, they should be declared const char* ptr = "hello"; for the reason that modifying a string literal invokes undefined behavior. Meaning that modifying it is a bug and might cause a program crash. This is a known flaw in C - the type of the string literal itself, even though we aren't allowed to write to it, is char[]. This is for historical reasons. In C++ however, they have fixed this language flaw inherited from C, so all string literals are const char[] in C++.

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

#2


2  

Consider the following:

考虑以下:

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

a just points to a character. That might be the first character of a string, or a single byte. That character can be modified by writing *a='Z' or a[0]='q' or by passing a to a function taking a char* parameter. The pointer itself can also be modified to point at some other characters, e.g. a=b; or a="foo";. This is the most flexible form, and the least safe, because you can do anything with it.

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

b is a constant pointer to a character. In this case, it's pointing at an array of characters. Those characters can be modified, e.g. b[1]='a'; or *b=0; but b itself is constant, meaning that it cannot ever point at a different part of memory. This form may be used when you have allocated a buffer or array whose contents you want to modify, but which cannot move, since it was allocated by the operating system.

b是指向字符的常量指针。在这种情况下,它指向一个字符数组。这些字符可以被修改,例如B [1] = 'A';或* b = 0;但是b本身是不变的,这意味着它不能指向记忆的不同部分。当您分配了一个缓冲区或数组,其内容要修改但无法移动时,可以使用此表单,因为它是由操作系统分配的。

c points to a constant character. You can change what it points at (c="foo"; or c=b;) but you cannot use this pointer to change the characters that it points at -- even if it's pointing at the non-constant buffer b. This form is commonly used when handling pre-generated strings. You can use this variable to store strings you've found, and pass their address around, as long as you don't change the strings themselves.

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

d is a constant pointer to a constant character. You can't change the characters it's pointing at, and you can't point the pointer itself at a different memory location. All you can do is read the string or individual characters (char e=d[4]; or puts(d);). This form is mainly used when passing around reference strings, for example when naming real objects.

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

#3


1  

  1. When you use this statement

    当您使用此声明时

    char *str = "Stack Overflow";
    

    it means that str points to string "Stack Overflow", which is stored in code memory and user is not allowed to modify it. So for this statement, writing const before char *str doesn't have any effect because the string is already constant.

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

    But const plays important role when you are pointing towards the base address of array, like

    但是,当你指向数组的基地址时,const会扮演重要角色

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

    Use of const means you can't modify the string in arr through the pointer str.

    使用const意味着你不能通过指针str修改arr中的字符串。

  2. When you are using

    当你使用

    char * const ptr;
    

    it means that ptr can't point to another address other than it's initial address. It is used when you do not intend to change the pointer address throughout the entire program, e.g. pointing to look up tables in embedded systems.

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

#1


4  

Code such as int *const a; is nonsense in most use-cases. The main use of making a pointer const is when you have a pointer-based look-up table. Or when you want a pointer to be stored in read-only memory on an embedded system.

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

Some confused programmers like to write code like void func (int* const ptr) but this is only obfuscation, in my opinion, since ptr is a copy of the original pointer anyhow, and the caller couldn't care less what the function does with its local copy internally.

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

Not to be mixed up with const correctness, which means that pointers to read-only data should be declared as const int* ptr. This is widely recognized as good programming practice, and it is canonical C, since most of the C standard utilizes const correctness for the C standard library.

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

As for pointers to string literals (like "hello") specifically, they should be declared const char* ptr = "hello"; for the reason that modifying a string literal invokes undefined behavior. Meaning that modifying it is a bug and might cause a program crash. This is a known flaw in C - the type of the string literal itself, even though we aren't allowed to write to it, is char[]. This is for historical reasons. In C++ however, they have fixed this language flaw inherited from C, so all string literals are const char[] in C++.

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

#2


2  

Consider the following:

考虑以下:

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

a just points to a character. That might be the first character of a string, or a single byte. That character can be modified by writing *a='Z' or a[0]='q' or by passing a to a function taking a char* parameter. The pointer itself can also be modified to point at some other characters, e.g. a=b; or a="foo";. This is the most flexible form, and the least safe, because you can do anything with it.

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

b is a constant pointer to a character. In this case, it's pointing at an array of characters. Those characters can be modified, e.g. b[1]='a'; or *b=0; but b itself is constant, meaning that it cannot ever point at a different part of memory. This form may be used when you have allocated a buffer or array whose contents you want to modify, but which cannot move, since it was allocated by the operating system.

b是指向字符的常量指针。在这种情况下,它指向一个字符数组。这些字符可以被修改,例如B [1] = 'A';或* b = 0;但是b本身是不变的,这意味着它不能指向记忆的不同部分。当您分配了一个缓冲区或数组,其内容要修改但无法移动时,可以使用此表单,因为它是由操作系统分配的。

c points to a constant character. You can change what it points at (c="foo"; or c=b;) but you cannot use this pointer to change the characters that it points at -- even if it's pointing at the non-constant buffer b. This form is commonly used when handling pre-generated strings. You can use this variable to store strings you've found, and pass their address around, as long as you don't change the strings themselves.

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

d is a constant pointer to a constant character. You can't change the characters it's pointing at, and you can't point the pointer itself at a different memory location. All you can do is read the string or individual characters (char e=d[4]; or puts(d);). This form is mainly used when passing around reference strings, for example when naming real objects.

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

#3


1  

  1. When you use this statement

    当您使用此声明时

    char *str = "Stack Overflow";
    

    it means that str points to string "Stack Overflow", which is stored in code memory and user is not allowed to modify it. So for this statement, writing const before char *str doesn't have any effect because the string is already constant.

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

    But const plays important role when you are pointing towards the base address of array, like

    但是,当你指向数组的基地址时,const会扮演重要角色

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

    Use of const means you can't modify the string in arr through the pointer str.

    使用const意味着你不能通过指针str修改arr中的字符串。

  2. When you are using

    当你使用

    char * const ptr;
    

    it means that ptr can't point to another address other than it's initial address. It is used when you do not intend to change the pointer address throughout the entire program, e.g. pointing to look up tables in embedded systems.

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