在C语言中,声明一个二维字符数组还是一个不规则的字符串数组更节省空间?(具体问题如下)

在C语言中,声明一个二维字符数组还是一个不规则的字符串数组更节省空间?(具体问题如下),c,arrays,string,performance,char,C,Arrays,String,Performance,Char,我有一个关于空间效率的具体问题,如下所示: 假设您要声明一个由7个字符串文字组成的数组,这些文字表示彩虹的7种颜色(即红色、橙色、黄色、绿色、蓝色、靛蓝和紫色)。假设指针的大小是8字节,那么在空间上声明二维字符数组还是不规则的字符串数组更有效 C中的字符串让我感到困惑,我不确定我现在是否要讨论这个问题。任何帮助都将不胜感激,尤其是即使使用少量代码来演示。提前谢谢大家 编辑: 我编写了以下代码: #include <stdio.h> #include <string.h>

我有一个关于空间效率的具体问题,如下所示:

假设您要声明一个由7个字符串文字组成的数组,这些文字表示彩虹的7种颜色(即红色、橙色、黄色、绿色、蓝色、靛蓝和紫色)。假设指针的大小是8字节,那么在空间上声明二维字符数组还是不规则的字符串数组更有效

C中的字符串让我感到困惑,我不确定我现在是否要讨论这个问题。任何帮助都将不胜感激,尤其是即使使用少量代码来演示。提前谢谢大家

编辑: 我编写了以下代码:

#include <stdio.h>
#include <string.h>

int main(void) {
    char *string_array[] = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"};
    char char_array[][7] = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"};

    printf("\nThe size of a string is: %lu", sizeof(char *));
    printf("\nThe size of a string array with the given data is: %lu", sizeof(string_array));
    printf("\nThe size of a char is: %lu", sizeof(char));
    printf("\nThe size of a char array with the given data is: %lu", sizeof(char_array));

    return 0;
}
我不确定这是否正确,因为我预期第一个数组(字符串的参差不齐数组)会更大?

选项1:

const char*颜色=[“红色”、“橙色”、“黄色”、“绿色”、“蓝色”、“靛蓝”、“紫色”];
在这里,所有字符串都会占用所需的只读内存(
43
bytes),但会使用额外的
56
(8字节的7个指针)字节将所有7个指针存储在内存中,从而总共产生
99
字节

备选案文2:

const char colors[][7]=[“红色”、“橙色”、“黄色”、“绿色”、“蓝色”、“靛蓝”、“紫色”];
这里声明一个2D数组,但由于需要在编译时声明第二维,因此它必须足够大,以容纳数组中最长的字符串(对于空终止字节,每个字符串中有1个字节)。因此,您最终会在所有较短的字符串上浪费空间

这里
49
(7个字符串,共7个字节),总共分配了字节,但为了存储所有字符串,总共只需要
43个
字节,因此6个字节被“浪费”


结论
总而言之,第二个选项需要更少的内存。

选项1和选项2:请参阅bool3max答案

选择3

char *data = "red\0orange\0yellow\0"
      "green\0blue\0indigo\0violet";
skiprint(data, 3);


一些C语言特有的知识是字符串以零字节结尾(称为NUL终止符)。所以字符串“red”实际上是四个字节
{r',e',d','\0'}
。此外,您还可以编写一个程序来测试您的理论,并使用
sizeof
查看数组使用的字节数。声明一个由所有7个字符串文本组成的字符指针数组,例如
const char*colors=[“red”,“orange”,…]
需要为所有字符串文本提供只读空间,并为所有指针提供额外的
7*8
字节,不是吗?计算机中有大量的字节,而不必担心有十几个左右的字节。如果你有一个2D数组,你需要为
NUL
计算出最长的字符串+1,这样就更容易,也不容易出错,让它成为一个1D字符串指针数组。即使你感到困惑,你自己对此有什么想法?你怎么认为?你自己的计算是什么?请回答您的问题以添加这些详细信息。您知道如何声明和初始化这两个选项吗?我觉得用你的声明来解释如何计算字节或如何声明其中一个或两个对你和其他人都更有用,而不是A或B占用更少的内存。我在写了一些代码后编辑了我的问题,它似乎与您在这里展示的有很大不同?您似乎是在32位系统上编译代码,在这个系统上,指针的大小为4字节,正如您在第一次
printf
调用中看到的那样。第二次调用确认:数组总共存储了4个字节的7个指针:
28
字节。这就为第一个声明方法留下了
71
字节,在内存使用方面,第二个方法仍然获胜。请注意,字符串常量可能使用多于或少于43个字节:如果编译器/链接器在4或8个字节的边界上对齐每个字符串,则会使用更多字节,如果这些字符串中的一些与程序中的其他字符串常量共享(相同或一个是另一个字符串常量的后缀),则可能会更少,例如
“blue”
“深蓝”
可能仅一起使用10个字节。此外,如上所述,在OP的程序中,字符串常量实际上不会出现在程序可执行文件中,因为编译器(包括
gcc
clang
)可以确定程序未使用实际字符串值。试图优化和测量实际结果是非常棘手的。
char *data = "red\0orange\0yellow\0"
      "green\0blue\0indigo\0violet";
skiprint(data, 3);
void skiprint(const char *zs, int n) {
    while (n--) { while (*zs) zs++; zs++; }
    puts(zs);
}