繁体   English   中英

在 C 中声明指向字符串的指针数组有什么缺点?

[英]What are the disadvantages of declaring an array of pointers to strings in C?

如果未声明为常量,则声明指向字符串文字的指针数组是否有任何负面影响?

我正在设置一个可以具有不同长度的字符串数组。 如果我将它们设置为指向字符串文字的指针数组,一切似乎都可以正常工作,我什至可以稍后更改它们。 我只是想确定这是最好的方法,然后再在更大规模的嵌入式程序中继续使用它。

  • 这个简单的例子是否有任何负面影响可能会丢失?
  • 将其声明为具有最大长度的二维字符数组是否有任何优势?

例子:

#include <stdio.h>

char * OutputNames[20] = 
{
    "Output 01",
    "Output 02",
    "Output 03",
    "Output 04",
    "Output 05",
    "Output 06",
    "Output 07",
    "Output 08",
    "Output 09",
    "Output 10",
    "Output 11",
    "Output 12",
    "Output 13",
    "Output 14",
    "Output 15",
    "Output 16",
    "Output 17",
    "Output 18",
    "Output 19",
    "Output 20",
};

char main()
{
    OutputNames[12] = "Test Output";
    for (unsigned char ArrMem = 0; ArrMem < 20; ++ArrMem)
    {
        printf("%s\n", OutputNames[ArrMem]);
    }
    
    getchar();
    return (0);
}

C 中的字符串文字是只读的(即使它们的类型实际上是char [] ),因此最好将数组定义为:

const char * OutputNames[] =
{
   ...
};

请注意,这意味着指针指向的是const ,而不是指针本身。 另外,请注意,数组长度被排除在外,因此大小可以由初始化程序指定。

不,这将是我存储具有不同长度的字符串集合的首选方式。

所需的内存量要多一点,因为您还存储了所有指针。 但是如果你创建一个二维数组,你会浪费更多的内存,因为每个字符串都需要足够的空间来容纳最长的字符串。

您需要担心的主要问题是释放所有内存,但由于您使用的是字符串常量,因此这不是问题。 我会将数组const

主要的危险是您可能会意外地尝试更改字符串文字之一(可能在某些调用链中传递指针的深处;难以调试)导致未定义的行为。 省去头疼的麻烦,并将它们声明为常量:

const char *OutputNames[20] = ...

请注意,这不会将 ARRAY 声明为常量,而只是将指向的字符串声明为常量。 因此,您仍然可以更改数组的任何元素(使其指向不同的字符串)。

如果您确实想在运行时更改字符串,那么一切都错了,您应该改用数组。

这个简单的例子是否有任何负面影响可能会丢失?

  • 如前所述,不小心执行写访问会调用未定义的行为。 绝对没有理由不将指针声明为const char*

  • 由于这是一个嵌入式系统,因此错误地声明了指针表。 您不仅需要指向只读数据的指针,指针本身也应该是只读的,因此数组在闪存而不是 RAM 中分配。 所以它实际上必须是const char* const类型。

这是假设冯诺依曼。 在哈佛架构的情况下,您可能需要添加一些丑陋的技巧,例如非标准关键字。

将其声明为具有最大长度的二维字符数组是否有任何优势?

这可能会带来更好的性能。 首先,您可以保证相邻分配。 这会在具有数据缓存支持的系统上带来更好的性能。 由于这些将在闪存中分配,因此访问通常很慢,具有等待状态。

其次,你摆脱了一个完整的指针查找表,它节省了内存并可能提供稍微更快的访问,因为你放弃了一个间接级别。

缺点是二维数组不太灵活,您需要分配固定长度。


与您的问题无关, char main()完全是废话。 main() 不是您可以随意声明的通用函数,而是一个专门的函数。

  • 托管 (PC) 系统上的int main(void)int main(void)或可选的 argv + argc。
  • 独立(嵌入式)系统上的 main() 通常是实现定义的void main(void)因为从 main() 返回是毫无意义的。 使用类似 gcc 的编译使用-ffreestanding编译。

无论哪种情况,决定 main() 的有效形式的是编译器,而不是程序员。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM