【问题标题】:Pointer to Char Initialization in CC 中指向 Char 初始化的指针
【发布时间】:2016-09-28 09:31:37
【问题描述】:

如果此代码正确:

char v1[ ]  =  "AB";     
char v2[ ]  = {"AB"};
char v3[ ]  = {'A', 'B'};
char v4[2]  =  "AB";     
char v5[2]  = {"AB"};
char v6[2]  = {'A', 'B'};
char *str1  =  "AB";
char *str2  = {"AB"};

那为什么另一个不是呢?

char *str3  = {'A', 'B'};

据我所知(如果我在任何时候错了,请纠正我)“AB”是字符串文字,“A”和“B”是字符(整数、标量)。在 char *str1 = "AB";定义了字符串文字“AB”,并将 char 指针设置为指向该字符串文字(指向第一个元素)。用 char *str3 = {'A', 'B'};定义了两个字符并将其存储在随后的内存位置中,并且 char 指针“应该”设置为指向第一个字符。为什么不正确?

以类似的方式,像 v3[] 或 v6[2] 这样的常规字符数组确实可以使用 {'A', 'B'} 进行初始化。这两个字符被定义,数组被设置为指向它们,因此,被“变成”或被视为字符串文字。为什么像 char *str3 这样的 char 指针的行为方式不同?

仅作记录,我得到的 gcc 编译器警告是当它到达“A”时“初始化从整数生成指针而不进行强制转换”,当它到达“B”时“标量初始化器中的多余元素”。

提前致谢。

【问题讨论】:

  • 指针不是数组,数组不是指针。可以在类似的上下文中使用,但它们并不相同。它们不同的一种方式是它们的初始化方式。
  • "AB" 是您指出的字符串文字,但 { 'A', 'B' } 不是,也不是任何类型的数组。它是用于初始化变量的数据,因此 a) 类型错误,并且 b) 提供了多个初始化器。
  • 这个char *str3 = (char[]) {'A', 'B'}; 可以工作... :-)
  • 感谢所有人 (@alk @WeatherVane @JoachimPileborg) :) 这是有道理的:1)“AB”是编译器已经分配的未命名字符串,然后可以通过数组或一个 char 指针(无需分配新内存)。 2) {'A', 'B'} 只是初始化器。因此,最终表现不符合概念预期的是数组,因为它们可以同时被初始化:1)分配内存并初始化它们(char v3[ ] = {'A', 'B'};)2)不分配内存,而只是让它们指向一个已经分配的未命名的字符串 (char v1[ ] = "AB";)。
  • 这两行:char v4[2] = "AB"; char v5[2] = {"AB"}; 不正确。因为字符串总是以 NUL 字节结束。但是,这两个变量声明只允许 2 个字节,而实际字符串长度是 3,而不是 2

标签: c string pointers initialization braces


【解决方案1】:

关于常量字符串文字,您需要了解一件事。除非用于初始化数组(例如,在您的示例代码中 v1 的情况下)常量字符串文字本身就是数组。例如,如果您使用文字 "AB",编译器会将其作为三个字符的数组存储在某处:'A''B' 和终止符 '\0'

当您初始化指向文字字符串的指针时,如str1str2 的情况,那么您将让这些指针指向这些数组中的第一个字符。你实际上并没有创建一个名为 str1 的数组(例如),你只是让它指向某个地方。

定义

char *str1 = "AB";

等价于

char *str1;
str1 = "AB";

或者说

char unnamed_array_created_by_compiler[] = "AB";
char *str1 = unnamed_array_created_by_compiler;

您显示的定义还有其他问题。首先是数组v3v4v5v6。您告诉编译器它们将是两个 char 元素的数组。这意味着您不能将它们用作 C 中的字符串,因为字符串需要特殊的终止符 '\0'

事实上,如果您检查 v1v2 的大小,您会发现它们确实有 三个 字节大,每个字符加上终止符一个字节。

您错过的另一件重要事情是,虽然常量字符串文字是 char 的数组,但您错过了 constant 部分。字符串文字实际上是只读的,即使没有这样存储。这就是为什么你永远不应该创建指向char 的指针(如str1str2)来指向它们,你应该创建指向constant char 的指针。即

const char *str1 = "AB";

【讨论】:

  • 非常感谢@JoachimPileborg 的详细回答,现在我理解得更好了:) 我认为我缺少的关键点是“常量字符串文字本身就是数组”及其解释。关于 constant 部分,我也不知道。我会彻底检查,因为我通常将 char *str 与字符串(“AB”)一起使用并修改其 char 元素。
【解决方案2】:

(" ") 用于字符串, (' ') 用于字符。对于字符串,已分配内存,而对于字符则没有。指针指向一个内存,你必须为它分配一个指定的内存,但是对于字符数组是没有必要的。

【讨论】:

  • 那么,如果对于一个数组不需要分配内存,为什么这段代码是正确的呢? char v3[ ] = {'A', 'B'};这里需要分配内存,然后用每个元素初始化字符数组。
  • 当你用c语言创建一个数组时,内存是自动分配的,但是对于指针,你需要通过“malloc函数”来分配内存,如下所示:str3 = (char *)malloc(sizeof(char )*Num);
  • 感谢@M.zanousi 的反馈 :) 我知道指针和动态内存分配。只是想知道 C 中数组声明的一致性。A)当我们在 C 中声明数组时,会自动分配一些内存,并且 B)为字符串(“”)分配内存,但不为字符(´´)分配内存。然后这段代码char v3[ ] = {'A', 'B'}; 有意义(数组分配和字符不分配,所以它们被放在那里)。但是,这段代码对我没有意义char v1[ ] = "AB";,因为有 2 个内存分配,1 个用于数组,另一个用于字符串“AB”。我错过了什么?
猜你喜欢
  • 2011-04-10
  • 1970-01-01
  • 2012-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-09
相关资源
最近更新 更多