【问题标题】:Why can a char pointer variable be initialized to a string but an int pointer variable can not be initialized to an array of integers? [duplicate]为什么 char 指针变量可以初始化为字符串,而 int 指针变量不能初始化为整数数组? [复制]
【发布时间】:2017-09-19 18:00:36
【问题描述】:

我试图理解字符串、数组和指针之间的关系。

我正在阅读的这本书有一个程序,它在其中初始化一个变量,如下所示:

char* szString= "Name";

我理解这一点的方式是,C 风格的字符串只是一个字符数组。数组只是引用指针(存储数组的第一个值)和偏移量的简写版本。 IE。 array[5] 实际上返回从表达式 *(array+5) 评估的内容。

所以,根据我的理解和测试,szString 实际上被初始化为一个指针,它指向存储“名称”的数组的第一个地址。我可以推断出这一点,因为输出为:

cout << *szstring;

是字符“N”。

我对声明的理解

cout << szstring;

输出字符“Name”,是方法cout将参数szstring解释为字符串类型,并打印出所有字符,直到NUL字符。另一方面,对于参数 *szstring,使用了支持 C 样式字符串的不同版本的此方法。

因此,如果我可以初始化一个 char 类型指针来寻址 chars 数组(C 样式字符串)中的第一个元素,为什么我不能初始化一个指向整数数组中第一个元素的 int 类型指针如下:

int* intArray = {1,2,3};

【问题讨论】:

  • “数组只是引用指针的简写版本” - 不,它不是。阅读一本好的 C 或 C++ 教科书,了解它的实际含义。
  • +1。我不知道为什么人们不赞成这个;这是一个有趣的问题。我一直认为"Name" 会很乐意留出我们可以获取指针的静态存储,但{1,2,3} 不会;但是现在看到这个问题,我意识到我不知道为什么会这样。
  • 是的,我也没有得到反对票和接近票。这是一个合理的问题,并没有像亲近的选民所认为的那样过于宽泛。
  • 简短回答:因为字符串文字历来在 C 语言中具有特殊地位。
  • 为什么不能初始化指向整数数组中第一个元素的 int 类型指针 -- {1,2,3} 不是数组,它被称为 list initialization 和它的实际作用取决于上下文。顺便说一句,char* str = { 'a', 'b', 'c' } 也是不允许的。

标签: c++ arrays string pointers


【解决方案1】:

C 风格的字符串只是一个字符数组

正确。

数组只是引用指针(存储数组的第一个值)和偏移量的简写版本。

不,不是。

方法 cout 将参数 szstring 解释为字符串类型并打印出所有字符,直到 NUL 字符

cout 不是“方法”,但它的operator&lt;&lt; 是这样工作的。

为什么char指针变量可以初始化为字符串,而int指针变量不能初始化为整数数组?

简单的答案是字符串文字是特殊的,否则我们将无法使用它们。

在许多方面,包括这种方式,语言标准都规定了对字符串文字和char*s 的特殊处理。

为什么我不能初始化指向整数数组中第一个元素的 int 类型指针

C++ 可以最终扩展了其他指针初始化的语法来做类似的事情,但它实际上并不需要,因为相反我们有更优越的:

std::vector<int> myInts{1,2,3};

【讨论】:

  • Re:“字符串字面量是特殊的,否则我们将无法使用它们”:显然,我们可以使用数组初始化器,而无需它们以这种方式“特殊”。你能解释一下为什么字符串文字必须不同吗?
  • @ruakh:好的,如果没有大量的不便、无休止的副本等,我们将无法使用它们。
  • @ruakh 我们不得不说{ 'a','b',c', 0 } 而不是"abc"。
  • @FilipGajowniczek:这就是数组下标的定义方式,是的。
  • @NeilButterworth:在char p[] = { 'a','b','c', 0 } 中,p 提供存储(在堆栈上分配),而不是数组初始值设定项。和写char p[4]; p[0] = 'a'; p[1] = 'b'; p[2] = 'c'; p[3] = '\0';一样。
【解决方案2】:

简短的回答是存在字符数组文字,但没有 int 数组文字。

字符串字面量是数组类型的字面值,它是一个左值,所以你可以获取和存储它的地址。这样的值所指定的对象的生命周期是永久的,因此得到的指针在整个程序中都是有效的。

相比之下,没有“int 数组”类型的字面量,也没有未命名的 int 数组左值。

不要将此与括号初始化列表混淆,后者是 not 表达式,因此不是值!花括号列表可用于初始化数组类型的变量,但它们本身不是值。

如果有的话,语言语法中唯一的奇怪之处在于,允许使用花括号列表初始化 char 数组包含字符串文字:char a[] = {"foo"}; 将其视为一种复制初始化; a 是文字左值的副本。

【讨论】:

    【解决方案3】:

    作为初学者,我也有类似的问题。请查看this post 和答案。

    这个const char* szString= "Name" 将一个数组的初始元素的地址分配给指针szString,该数组的内容是“名称”(后跟一个终止的“\0”空字符)。

    没有从 int 到 int* 的隐式转换,除了 0 是一种特殊情况,作为空指针。

    【讨论】:

    • @dirty_feri:你错了。自 C++98 以来它已被弃用(意思是“不要这样做”)并且自 C++11 以来是非法的(意思是“你不能这样做”)。不要参考一些随机的过时教程;参考文档、语言标准和由专家撰写的经过同行评议的书籍。
    • @Filip:它叫做“Visual Studio”。它必须有一个扩展名。那是非法的 C++。
    • @dirty_feri:见上文。我们已经确定 VS 在这方面是不合规的。
    • @FilipGajowniczek:来源很重要,因为字符串文字可能永远不会被修改。如果没有const,您只需要记住不要尝试修改它们;有了它,编译器会为您强制执行该规则。他们真的应该从 C++ 的第一个版本开始就需要const,但是嘿嘿。 (而且,不,指针可能是 4 字节、8 字节,或任何其他字节数;这取决于您的系统。)
    • @FilipGajowniczek:是的,它们是硬编码的(通常是在可执行文件的“数据”区域中),这就是为什么你不能成功/安全地修改它们的原因。但是,如果您在 C++98(或不兼容)实现中省略了 const,那么您当然可以尝试:szString[0] = '!'; 然后看火花飞溅。
    猜你喜欢
    • 2016-06-27
    • 1970-01-01
    • 2021-05-18
    • 2019-04-09
    • 1970-01-01
    • 2015-08-03
    • 2012-08-23
    • 2016-11-27
    • 2016-09-04
    相关资源
    最近更新 更多