【问题标题】:Different Types Of Initializing Character Arrays in CC语言中初始化字符数组的不同类型
【发布时间】:2021-11-23 07:36:25
【问题描述】:

我正在学习指针和字符串。 我明白了,

  1. 指针和数组/字符串具有相似的行为。
  2. 数组[]、*数组、&数组[0]。它们都是一体的。

为什么这段代码中的三个语句有效,而char * help 一个无效?

#include <stdio.h>

void display(char*help){
    for(int i=0; help[i]!='\0'; i++){
        printf("%c", help[i]);
    }
}
int main(){ 
    // char help[] = "Help_Me";                                 //Works 
    // char help[] = {'H','e','l','p','_','M','e','\0'};        //Works
    // char *help = "Help_Me";                                  //Works
    char *help = {'H','e','l','p','_','M','e','\0'};            //Error 
    
    display(help);
}

错误信息:

警告:从 'int' 初始化 'char *' 会使指针从整数变为无强制类型转换
警告:标量初始化器中的多余元素

【问题讨论】:

  • char *help = {'H','e','l','p','_','M','e','\0'}; 真的等同于 char *help = '\0'; 和任何其他文字字符一样,'\0' 将被提升为 int
  • 您不能使用初始化列表来初始化指针。您可以使用复合数组文字来做到这一点。 en.cppreference.com/w/c/language/compound_literal
  • 不,array[]*array&amp;array[0] 在含义和拼写上都是不同的。
  • array[] , *array , &array[0] 根本不一样。

标签: c string pointers


【解决方案1】:
  1. 指针和数组/字符串具有相似的行为。

实际上,不,我不同意这一点。这是隐藏重要细节的过度简化。真实情况是数组几乎没有自己的行为,但在大多数情况下,指定数组的左值会自动转换为指向第一个数组元素的指针。生成的指针的行为当然类似于指针,这可能会呈现出指针和数组具有相似行为的外观。

此外,数组是对象,而字符串是char 数组可以包含的某些数据配置。尽管人们有时会将字符串与包含它们的数组或指向它们的第一个元素的指针混为一谈,但这在形式上是不正确的。

  1. 数组[]、*数组、&数组[0]。它们都是一体的。

不,一点也不,尽管差异取决于它们出现的上下文:

array 的声明中(函数原型除外)

  • type array[]array 声明为 type 的数组,其大小将由其初始化程序确定;
  • type *arrayarray 声明为指向 type 的指针;和
  • &amp;array[0] 不是 array 的任何有效声明的一部分。

在函数原型中

  • type array[]type *array 一样被自动“调整”,因此它将 array 声明为指向 type 的指针;
  • type *arrayarray 声明为指向 type 的指针;和
  • &amp;array[0] 不是 array 的任何有效声明的一部分。

在表达式中

  • array[] 无效;
  • *array等价于array[0],表示array的第一个元素;和
  • &amp;array[0]指向 array[0] 的指针。

现在,你问,

为什么这段代码中的三个语句都有效,而char * help one却无效?

"Help_Me" 是一个字符串文字。它指定一个静态分配的数组,其大小刚好足以包含指定的字符和一个字符串终止符。作为一个数组值表达式,在大多数情况下它被转换为指向其第一个元素的指针,并且这样的指针具有正确的类型以用于...

    // char *help = "Help_Me";                                  //Works

但是字符串文字作为char数组的初始值设定项的出现...

    // char help[] = "Help_Me";                                 //Works 

... 是数组值不会自动转换为指针的少数上下文之一。在这种情况下,由字符串字面量指定的数组元素用于初始化正在声明的数组,非常类似于 ...

    // char help[] = {'H','e','l','p','_','M','e','\0'};        //Works

。在那里,{'H','e','l','p','_','M','e','\0'} 是一个数组初始值设定项,指定 8 个数组元素的值。请注意,作为一个整体,它本身并不是一个值,而只是 int(C 中)或 char(C++ 中)类型的八个值的语法容器。

这就是为什么...

    char *help = {'H','e','l','p','_','M','e','\0'};            //Error

...没有意义。在那里,help 是一个标量对象,而不是数组或结构,所以它只取一个值。该值的类型为char *。编译器发出的警告告诉您已经显示了 8 个值而不是 1 个,并且它们有,或者至少用于初始化的那个有,输入 int 而不是输入 char *

【讨论】:

    【解决方案2】:

    数组[]、*数组、&数组[0]。它们都是一体的。

    没有。假设 array 命名了某个数组,array[] 不能在表达式中使用(除非它可能出现在某些类型描述中,例如强制转换)。

    array 本身在表达式中会自动转换为指向其第一个元素的指针,除非它是 sizeof 的操作数或一元 &amp; 的操作数。 (另外,字符串字面量,如"abc",表示一个数组,这个数组在转换时还有一个例外:当它用于初始化数组时。)

    *array中,array会自动转换为指针,然后*指向它所指向的元素。因此*array 指的是数组中的一个元素;它不是指向数组或其元素的指针。

    &amp;array[0]中,array[0]指的是数组的第一个元素,然后&amp;取它的地址,所以&amp;array[0]是一个指向数组第一个元素的指针。这使得它等同于表达式中的array,除了上面提到的例外。例如,void *p = array;void *p = &amp;array[0]; 会将p 初始化为相同的东西,一个指向数组第一个元素的指针,因为自动转换。但是,size_t s = sizeof array;size_t s = sizeof &amp;array[0]; 可以将 s 初始化为不同的值——第一个为整个数组的大小,第二个为指针的大小。

    // char help[] = "Help_Me"; //Works

    helpchar 的数组,字符数组可以用字符串字面量初始化。这是初始化的特殊规则。

    // char help[] = {'H','e','l','p','_','M','e','\0'}; //Works

    help 是一个数组,初始值设定项是数组元素的值列表。

    // char *help = "Help_Me"; //Works

    help 是一个指针,"Help_Me" 是一个字符串文字。因为它不在其中一个例外中——sizeof 的操作数、&amp; 的一元操作数或用于初始化数组——它会自动转换为指向其第一个元素的指针。然后help 用那个指针值初始化。

    char *help = {'H','e','l','p','_','M','e','\0'}; //Error

    help 是一个指针,但初始化程序是一个值列表。只有一件事要初始化,一个指针,但它列出了多个值,所以这是一个错误。此外,应该使用指针值(地址或空指针常量)初始化指针,但该列表中的项目是整数。 (字符文字是整数;它们的值是字符的代码。)

    {'H','e','l','p','_','M','e','\0'} 不是创建字符串或数组的语法。它是一种语法,可用于在初始化对象时提供值列表。所以编译器不会将其识别为字符串或数组,也不会使用它来初始化指针help

    【讨论】:

      【解决方案3】:

      指针不是数组,不能像数组一样初始化。您需要创建一个对象,然后您可以将其引用分配给指针。

      char *help = (char[]){'H','e','l','p','_','M','e','\0'}; 
      

      【讨论】:

        猜你喜欢
        • 2022-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-26
        • 2020-11-09
        • 1970-01-01
        • 2023-04-03
        相关资源
        最近更新 更多