-1

在设计包含文本数据的结构时,我一直在使用两种基本方法,如下所示:

typedef struct {
    STRING address1;
    STRING address2;
    STRING city;
    STRING state;
    STRING zip;
} ADDRESS;

typedef struct {
    STRING* address1;
    STRING* address2;
    STRING* city;
    STRING* state;
    STRING* zip;
} ADDRESS;

其中 STRING 是一些可变长度的字符串存储类型。指针版本的优点是我可以存储表示数据丢失的 NULL。例如,可能没有为某些地址提供 address2。在嵌入字符串的类型中,我必须使用“空白”字符串,即长度为 0 的字符串。

使用指针(可能)会有更多的代码负担,因为我必须在使用之前检查每个成员是否为 NULL。然而,优势并不是那么大,因为通常也必须检查嵌入式版本。例如,如果我正在打印一个地址,我必须检查一个零长度的字符串并跳过该行。使用指针,用户实际上可以指示他们想要“空白”而不是缺失值,尽管很难看到这样做的用途。

在创建或释放结构时,指针会添加一堆额外的步骤。我的直觉是标准化嵌入式样式以节省这些步骤,但我担心可能存在隐藏的问题。这是没有根据的恐惧,还是我应该出于某种令人信服的原因使用指针?

请注意,内存使用是一个问题,但它非常小。指针版本需要更多内存,因为除了结构之外,我还存储指向结构的指针。但是每个字符串结构平均可能需要 40 个字节,所以如果我存储 4 个字节的指针,那么指针版本可能会多消耗 10% 的内存,这并不重要。可能使用空指针不会节省大量内存,因为大多数字段都已填充。

问题是关于地址而不是字符串

一些受访者似乎很困惑,认为我在询问全局权衡,例如如何最小化我的总工作量。事实并非如此。我问的是如何设计地址,而不是字符串。address 的成员可以有固定的数组,或者在其他情况下没有。就我的问题而言,我不关心容器的后果。

我已经说过,我能看到的唯一问题是使用指针需要更多时间,但我得到了能够存储 NULL 的好处。然而,正如我已经说过的,这种好处似乎并不显着,但也许是出于某种原因。这就是我的问题的本质:拥有这种灵活性是否有一些隐藏的好处,我没有看到并且希望我以后有。

如果你不明白这个问题,请阅读我在下面写的初步答案(经过一些额外的思考),看看我正在寻找的答案。

4

3 回答 3

2

权衡内存使用和减少 malloc

似乎权衡集中在两个问题上:1)内存有多宝贵?2)为字符串分配固定数量的内存是否重要,限制每个字段中存储的长度?

如果内存比其他任何东西都重要,那么指针版本可能会胜出。如果存储使用的可预测性和避免 malloc 是首选,并且将名称的长度限制在某个固定数量是可以接受的,那么固定长度版本可能是赢家。

于 2019-04-18T10:58:41.973 回答
0

嵌入式样式的一个问题是 STRING 需要定义为类似于char[MAX_CHAR + 1]whereMAX_CHAR是给定字段的悲观最大长度。指针样式允许分配正确数量的内存。您提到的缺点是管理结构的认知开销要高得多。

于 2019-04-18T10:54:03.113 回答
-2

我一直在更深入地考虑这一点,我认为在大多数情况下指针是必要的,因为区分空白和缺失很重要。这样做的原因是当输入无效或损坏或遗漏时需要丢失的数据。例如,假设从文件中读取时,文件已损坏,因此邮政编码等字段不可读。在这种情况下,数据“丢失”并且指针应该为 NULL。另一方面,让我们假设这个地方没有邮政编码,那么它就是“空白”。因此,NULL 表示用户尚未提供信息,而空白表示用户已提供信息并且没有任何类型的问题。

因此,为了进一步说明使用指针的重要性,想象一个复杂的结构随着时间的推移以不同的异步步骤填充。在这里,我们需要知道哪些字段已读取,哪些未读取。除非我们使用指针(或添加额外的元数据),否则我们无法区分已回答的字段与回答为“无”的字段之间的区别。想象一下系统提示用户“邮政编码是什么?”。用户说,“这个地方没有邮政编码”。然后 5 分钟后系统再次询问,“邮政编码是多少?”。该用例清楚地表明我们在大多数情况下都需要指针。

有鉴于此,我应该使用嵌入式结构的唯一情况是当容器结构被保证在创建时具有完整的数据集时。

于 2019-04-18T15:47:37.827 回答