【问题标题】:What is difference between char* and int* data type to create array of pointers in C++?在 C++ 中创建指针数组的 char* 和 int* 数据​​类型有什么区别?
【发布时间】:2016-07-06 21:59:19
【问题描述】:

在为int 数据类型创建指针数组时,以下代码有效:

int var[] = {10, 100, 200, 1000};
int *ptr[] = {&var[0], &var[1], &var[2], &var[3]};

在为char 数据类型创建指针数组时,以下是合法的:

char *names[] = {"Mathew Emerson", "Bob Jackson"};

但如果我为int 数据类型创建一个指针数组,如下所示:

int var[] = {10, 100, 200, 1000};
int *ptr[] = {var[0], var[1], var[2], var[3]};

我得到一个编译器错误。我理解为什么在上述int 数据类型数组的声明方法中出现编译错误,因为 var[i] 不是对指针必须指向的变量的引用,即它的地址,但不应该t 在我的 char 指针数组的声明中,同样的逻辑也会出错。

它在char 指针数组中可以接受的原因是什么?

字符串值”是指针可以指向的地址还是只是一个常量字符串值。

【问题讨论】:

  • 旁注:有些人认为var + 3&var[3] 更好。
  • 编译器将代码中出现的每一个带引号的字符序列(又名字符串文字)替换为您的代码正在执行的二进制映像中该序列的地址编译成。
  • @barak manos 所以每次将字符串分配给某个变量时,它的功能取决于变量的数据类型?如果变量是字符串类型,则分配实际值,如果变量是 char* 类型,则将字符串的地址分配给它?例如:char *str = "好"; cout
  • @Natsu:如果变量类型是std::string,那么std::string类的构造函数会用那个指针调用,并将指向的数据复制到调用对象中。

标签: c++ arrays pointers


【解决方案1】:
char *names[] = {"Mathew Emerson", "Bob Jackson"};

在 C++ 中是不合法的。字符串文字的类型为 const char[],因此将其存储为 char* 是非法的,因为它违反了 const 正确性。由于字符串文字的类型为char[],因此一些编译器允许它仍然作为 C 的遗留版本进行编译,但它不是标准的 C++。如果您在编译器上打开警告,您应该得到类似

的内容
main.cpp: In function 'int main()':
main.cpp:5:53: warning: ISO C++ forbids converting a string constant to 'char*' [-Wpedantic]
     char *names[] = {"Mathew Emerson", "Bob Jackson"};

如果你想要一个字符串数组,那么我建议你使用 std::string 之类的

std::string names[] = {"Mathew Emerson", "Bob Jackson"};

原因

char *names[] = {"Mathew Emerson", "Bob Jackson"};

“有效”是因为字符串文字是数组,它们隐式地衰减为指针,所以

{"Mathew Emerson", "Bob Jackson"}

变成

{ address_of_first_string_literal, address_of_second_string_literal}

然后这些用于初始化数组中的指针。

int *ptr[] = {var[0], var[1], var[2], var[3]};

无法工作,因为var[N] 是对数组中int 的引用,而不是指针。

【讨论】:

  • @Nelxost 已更正。
  • 问题在于字符串文字在 C 和 C++ 中具有不同的类型。在 C 中,字符串文字的类型为 char[]。它不是const(尽管修改其内容是未定义的行为)。在 C++ 中,字符串文字的类型为 const char[]
  • @CodyGray 谢谢你。那是我记错了。
【解决方案2】:

"Mathew Emerson" 的类型为const char* - 它已经是一个指针,因此您可以直接将它存储在一个指针数组中。对于 int 情况,您需要 & 的原因是将 int“转换”为 int*

【讨论】:

  • 其实你是在做一个往返:var: int[] or int* (隐式转换!) --> var[i]: int --> &var[i]: int*. ..
  • 我认为你的意思是“"Mathew Emerson" 的类型为 const char[15],并且可以衰减为指向其第一个元素的指针”。
【解决方案3】:

(忽略其他答案中提到的 const-ness 问题......)

您编写的每个字符串文字("Mathew Emerson""Bob Jackson"、...)都需要稍后在编译代码中的一些存储位置。

就好像你在什么地方写的一样

char const[] MathewEmerson = { 'M', 'a', /*...*/, 'o', 'n', 0 };

所以你可以构造你的 char const* 数组,然后:

char const* names[] = { &MathewEmerson[0], /*...*/ };

对于数组来说,数组本身的地址和它的第一个元素的地址是一样的,而且数组是隐式转换为指针的,可以改写

char const* names[] = { MathewEmerson, /*...*/ };

如果您使用字符串文字,所有这些都是为您隐式完成的。

同样,你也可以这样写:

int *ptr[] = {var, &var[1], &var[2], &var[3]};

(注意:var,不是&var[0] 第一项)如果我们更进一步,甚至:

int *ptr[] = {var, var + 1, var + 2, var + 3};

结果总是一样的。一种变体与另一种变体的可读性、可理解性?嗯,另一个话题……

【讨论】:

    【解决方案4】:

    您的误解包含在您对以下内容的解释中:"Mathew Emerson"

    这是一个字符数组,将作为程序引导的一部分在只读内存中实例化。这个字符数组称为String Literal,具体来说是:

    窄多字节字符串文字。无前缀字符串字面量的类型是const char[]

    NathanOliver's answer 正确描述了您的编译器没有将警告级别调得足够高,因此它允许const char[] 衰减为char*。这很糟糕,因为:

    尝试修改字符串文字会导致未定义的行为:它们可能存储在只读存储中(例如 .rodata)或与其他字符串文字组合[1]

    但是这样做是完全合法和合乎逻辑的:const char *names[] = {"Mathew Emerson", "Bob Jackson"} 希望这可以为您澄清正在发生的事情,让您了解使用字符串文字使用指针.您的代码:int *ptr[] = {var[0], var[1], var[2], var[3]} 是非法的,因为 var[0]int& 而不是 int*。这样做同样是非法的:char* ptr = {names[0][0], names[0][1], names[0][2], names[0][3]} 同样,这里的问题是我使用的是char&s 而不是char*s。

    【讨论】:

      猜你喜欢
      • 2016-12-02
      • 1970-01-01
      • 2020-08-20
      • 1970-01-01
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      相关资源
      最近更新 更多