【问题标题】:In C, how can I ensure that length of an initialized string is less than specified在 C 中,如何确保初始化字符串的长度小于指定的长度
【发布时间】:2017-09-06 02:37:21
【问题描述】:

我有一个struct,其中成员是一个最大长度为N 的字符串。定义:

typedef struct
{
    const char foo[N];
} bar_t;

我希望这个结构的用户初始化foo 成员,长度不超过N

bar_t mybar = { .foo = "12345678" };

在哪里N=8。由于我无法控制bar_t 的所有初始化,因此如果bar_t.foo 的长度大于N,我想依靠编译器生成警告/错误。

问题在于,为了说明终止符(为了能够将bar_t.foo 用作普通字符串),我需要指定长度为N+1bar_t.foo

或者,我可以将bar_t.foo 的长度设置为N,并在使用长度为> N 的字符串初始化时收到编译器警告,但我现在需要明确预期的字符串长度(即@987654337 @ 系列函数,以 N 作为最大长度参数)在使用需要终止符的函数时。

有没有办法让编译器限制初始化器的长度,并且还能够在不明确最大字符串长度的情况下处理字段?

【问题讨论】:

  • 相反的策略怎么样:总是将空字符附加到字符串文字:.foo = "12345678\0"?

标签: c string initializer


【解决方案1】:

GCC 不会警告字符串初始化器比分配的内存长,因为它是完全合法的。但是您可以使用类似于以下的宏和静态断言来提供编译时检查:

#include <stdio.h>

#define N 6
typedef struct
{
    const char foo[N];
} bar_t;

#define INIT_FOO(var, initString) \
     _Static_assert(sizeof(initString) < N, "Bad length!"); \
     bar_t var = { .foo = initString };

INIT_FOO(mybar, "Good");
//INIT_FOO(mybar, "Baaaad");

int main(void) {
    printf("%s\n", mybar.foo);
    return 0;
}

ideone上查看它的实际应用

【讨论】:

  • 因为它是完全合法的:好吧,gcc 也有针对有效但危险的构造的警告,所以我会说它没有它: )(据我所知)。其他一些编译器可能有这样的警告选项。请注意,PC-lint 对此有一条信息性消息 (784):Nul character truncated from string.
  • 谢谢。 _Static_assert() 可能是一种合理的方法。对于开发人员来说,它会使结构的使用更加麻烦。
猜你喜欢
  • 2020-05-03
  • 2014-04-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 2010-12-12
  • 2021-04-20
  • 2021-12-27
  • 2021-02-16
相关资源
最近更新 更多