【问题标题】:const char** vs const char* mutationconst char** 与 const char* 突变
【发布时间】:2019-05-24 15:42:26
【问题描述】:

在我的代码中,我尝试做以下事情:

// Attempt #1
const char** strings;
strings[0] = "apple";
strings[1] = "orange";
strings[3] = "bananas";

// Attempt #2
const char* chars;
chars[0] = 'a'; // Error
chars[1] = 'b'; // Error again

当我编译 GCC 时,尝试 #1 很好,但对于尝试 #2,它说 LHS 必须是可分配的。显然,凭借const 标识符,数组字符是不可分配的。为什么?

【问题讨论】:

  • 基本上你想要的是const char* strings[N]const char chars[N] 其中N 是元素的数量。要么,要么你在运行时使用malloc。在第二种情况下,您可以使用 const char chars[N] = { 'a', 'b' } 或直接删除 const...
  • 如果标准 not 允许在最前列的类型上使用 prefix-const(iow,要求 const 紧跟在类型,之前不是可选的,但只适用于最外面的类型)。
  • @DeiDei 为了一致性和统一性(也许是代码本身的性质),我反对使用数组括号。 (我宁愿做 *(ptr +N) = value 而不是 ptr[N])
  • @Ace 总有一天你会厌倦这样做,而真正厌倦,我的意思是厌倦了维护你的代码的同事要求你破译它,因为你是唯一的做这件事的团队中的一个。只是公平的警告。

标签: c pointers char


【解决方案1】:

const char** 读作“指向常量字符的(非常量)指针的(非常量)指针”。您可以修改stringsstrings[n],但不能修改strings[n][m]

const char* 只是一个级别。您可以修改chars 但不能修改chars[n]

使strings[n] 不可修改的方式是使用const char* const* -“指向const 指向常量字符的指针的(非常量)指针”

另请注意,在您的示例中 stringschars 未初始化。您需要先初始化它们,然后才能真正访问它们。

This question 具有如何阅读 C 声明的方法。在这些简单的情况下,您从右到左阅读。

【讨论】:

  • 谢谢你说得通。所以我的意图是让这两种情况下的数组指针都是不可变的。我只想更改包含在数组 [m] 或数组 [n] [m] 中的值本身。那么我们应该选择 char* const chars 吗?和 char** const 字符串?
  • 我也不确定你什么时候说变量没有初始化。我相信这正是我做的对吗?
  • @Ace 两者都没有被初始化。您正在执行任务。初始化不仅仅意味着“设定值”。这是一个特定语言的术语,意思是“在声明时建立价值”。 int x; x = 5; 声明一个未初始化的int,然后赋值5int x = 5; 声明并初始化x。 IE。 x在后续代码中不存在没有确定值。
  • @WhozCraig Gotcha 谢谢!这些变量在小型内联函数中受到严格控制。所以返回野指针(未初始化)的机会很小。但我同意你的观点。
  • @Ace 如果你有const char* chars;,你必须chars分配给某事(例如chars = ...;,然后你才能对chars[0]等做任何事情。
【解决方案2】:

char *string 是指向char 数组的指针。像这样:

             .----.   .----.   .----.
             | s  | - | a  | - | m  |
             .----.   .----.   .----.
               ^
               |
char *string --.

就像你有一个数组和一个指向数组的指针:

char strArr[3];
char *ptrToStr = &strArr;

您可以通过多种方式初始化char *

char *string;
scanf("%as", string);
/* if you don't allocate buffer for `*string`, and specify "a" in string format, 
then `scanf` will do it for you. this is GNU-only extension. */

char *string2;
string2 = (char *) malloc (BUFF_SIZE);
sprintf(string2, "%s" , "Ghasem Ramezani");

...

char **string 是一个指向char 数组的指针。像这样:

                     .----.   .----.   .----.
                     | s  | - | a  | - | 1  |
                     .----.   .----.   .----.
                       ^
                       |
   .->  char *string --.
   |                 .----.   .----.   .----.
   |                 | s  | - | a  | - | 2  |
   |                 .----.   .----.   .----.
   |                   ^
   |                   |
   .-> char *string2 --.
   |
   .-------------.
                 |
char **strArr ---.

例如char **,你还记得main () 中的argv 参数吗?这正是char ** 的类型。让我们看一个例子:

/*1*/ #include <stdio.h>
/*2*/ int main(int argc, char *argv[]) {
/*3*/   for (int i = 0; i < argc; ++i)
/*4*/     puts(argv[i]);
/*5*/   return 0;
/*6*/ }
$> gcc -o output main.c
$> ./output ghasem ramezani
./output
ghasem
ramezani
$>

正如您在第 2 行中看到的,我们可以写成 char *[] 而不是 char **。为什么 ?因为正如我和@Kevin 所说:

将 const char** 读取为“指向常量字符的(非常量)指针的(非常量)指针”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2023-03-15
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多