首页 > 解决方案 > char **s vs char *s[] 初始化

问题描述

我正在努力理解char *s[]char s**初始化之间的区别。我的char *s[]工作正常,而我的char s1**抛出错误[Error] scalar object 's1' requires one element in initializer。我不明白那个错误的含义。

我们怎样才能char s1**正确初始化?

#include<stdio.h>
int main(void)
{
    char *s[]={"APPLE","ORANGE"};
    char **s1={"APPLE","ORANGE"};
    return 0;
}

标签: arrayscstring

解决方案


TLDR char **s1=(char*[]){"apple","orange"};:。

当然,您可以使用数组中元素的地址来初始化指针。这在更简单的数据类型中更常见:假设int arr[] = {1,2};你可以说int *p = &arr[0];; 一个我讨厌的符号,在这里只是为了说明我们在做什么。由于数组无论如何都会衰减为指向其第一个元素的指针,因此您可以更简单地编写int *p = arr;. 请注意指针的类型是“指向元素类型的指针”。

现在您的数组s包含“指向字符的指针”类型的元素。你可以做和以前一样的事情。元素类型是指向 char 的指针,因此指针类型必须是指向它的指针,指向指向 char 的指针,正如您正确编写的那样:

char **s2= &s[0];,或者更简单char **s2= s;

现在这有点毫无意义,因为您s已经并且不再需要指针了。你想要的是一个“数组文字”。C99 引入了一个符号,该符号在元素列表前面加上一种类型转换。使用一个简单的整数数组,它看起来像这样int *p = (int []){1, 2};:使用您的 char 指针,它看起来像这样:

char **s1=(char*[]){"apple","orange"};.

警告:虽然字符串文字具有静态存储持续时间(即,指向它们的指针在程序结束之前保持有效),但由文字创建的数组对象却没有:它的生命周期以封闭块结束。如果封闭块是main这里的函数,那可能没问题,但是您不能,例如,在“初始化”例程中初始化一堆指针并稍后使用它们。

警告 2:最好将数组和指针声明为指向 const char,因为字符串文字通常在现代系统上不可写。您的代码仅出于历史原因编译;禁止char *s = "this is constant";会破坏太多现有的代码。(C++确实禁止,这样的代码不能编译成C++。但是在这种特殊情况下,C++没有这种复合字面量的概念,下面的程序是无效的C++。)我在下面的完整程序演示了复合文字的使用。您甚至可以获取它的地址,就像任何其他数组一样!

#include<stdio.h>
int main(void)
{
    /// array of pointers to char.
    const char *arrOfCharPtrs[2]={"APPLE","ORANGE"}; 
    
    /// pointer to first element in array
    const char **ptrToArrElem= &arrOfCharPtrs[0];
    
    /// pointer to element in array literal
    const char **ptrToArrLiteralElem=(const char*[]){"apple","orange"};

    /// pointer to entire array. 
    /// Yes, you can take the address of the entire array!
    const char *(*ptrToArr)[2] = &arrOfCharPtrs;
    
    /// pointer to entire array literal. Note the parentheses around
    /// (*ptrToArrLiteral)- Yes, you can take the address of an array literal!
    const char *(*ptrToArrLiteral)[2] = &(const char *[]){"apples", "pears"};
    
    printf("%s, %s\n", ptrToArrElem[0], ptrToArrElem[1]);
    printf("%s, %s\n", ptrToArrLiteralElem[0], ptrToArrLiteralElem[1]);
    printf("%s, %s\n", (*ptrToArr)[0], (*ptrToArr)[1]);
    
    // In order to access elements in an array pointed to by ptrToArrLiteral,
    // you have to dereference the pointer first, yielding the array object,
    // which then can be indexed. Note the parentheses around (*ptrToArrLiteral)
    // which force dereferencing *before* indexing, here and in the declaration.
    printf("%s, %s\n", (*ptrToArrLiteral)[0], (*ptrToArrLiteral)[1]);
    return 0;
}

示例会话:

$ gcc -Wall -pedantic -o array-literal array-literal.c &&  ./array-literal
APPLE, ORANGE
apple, orange
APPLE, ORANGE
apples, pears

推荐阅读