【问题标题】:How do I suppress PC-Lint errors for C99-style initialization of structure members?如何抑制结构成员的 C99 样式初始化的 PC-Lint 错误?
【发布时间】:2014-05-14 10:25:21
【问题描述】:

我正在使用带有以下选项的 PC-Lint 8.00x:

+v -wlib(1) +fan +fas

当我运行类似于以下的代码时,我从 PC-Lint 收到许多错误消息:

typedef union
{
    struct
    {
        unsigned int a : 4;
        unsigned int b : 4;
        unsigned int c : 4;
        unsigned int d : 4;
    } bits;
    unsigned short value;
} My_Value;

int main (void)
{
    My_Value test[] =
    {
        {
            .bits.a = 2,
            .bits.b = 3,    //Errors 133 and 10
            .bits.c = 2,
            .bits.d = 3,
        },
        {
            .bits.a = 1,
            .bits.b = 1,    //Errors 133 and 10
            .bits.c = 1,
            .bits.d = 0,
        },
    };

    /* Do something meaningful. */

    return 0;
}

报告的错误由 PC-Lint 定义如下:

错误 133:聚合“未知名称”的初始化程序过多

错误 10:需要 '}'

我尝试搜索 Gimpel 并进行了一些 Google 搜索,但我找不到任何有用的东西。代码按预期运行,一切都正确初始化。这是我的问题。

1. PC-Lint 8.00x 是否支持结构成员的 C99 样式初始化?

2。如果是这样,我必须为 PC-Lint 设置哪些选项/标志才能全局禁止这些消息?

编辑
关于问题 2,我应该更详细。我想在全局禁止这些消息,因为我使用了如上所示的指定初始化程序。我无法在所有情况下全局抑制它们,因为这些错误可以检测代码中的真正错误。

【问题讨论】:

  • 我不知道这样嵌套成员字段(例如.bits.a)是否真的可以。我怀疑你需要做例如My_value test[] = { { { .a = 2, .b = 3, .c = 2, .d = 3 } }, ... }.
  • @JoachimPileborg 这是一个很好的观点。我已经看到了一些使用指定初始化列表来初始化嵌套结构的示例(例如this),但我不确定这是否是正确的 C99。我可能需要提出另一个问题...
  • 看来我使用上面写的指定初始化列表是有效的。但是,我仍然无法让 PC-Lint 很好地配合这个特定的实现。
  • 我同意它是有效的;语法允许designator-list,并且.bits.a 限定(并且gcc 和clang 都接受它)。但是,如果您将.bits 上移一层会发生什么?
  • @KeithThompson,看起来你正在做某事。如果我更改为[0].bits.a = 1 并继续通过[1].bits.d = 0 PC-Lint 不再抱怨,armcc 仍然可以正确编译它。这可能是我最好的选择。

标签: c c99 lint pc-lint


【解决方案1】:

据我所知,这个语法:

My_Value test[] =
{
    {
        .bits.a = 2,
        .bits.b = 3,
        .bits.c = 2,
        .bits.d = 3,
    },
    {
        .bits.a = 1,
        .bits.b = 1,
        .bits.c = 1,
        .bits.d = 0,
    },
};

在 C99(和 C11)中有效。查看标准的第 6.7.8 节,初始化器中 = 之前的内容是 designator-list,它是一个或多个 designator 的序列. .bits.a 在该上下文中有效。

显然 PC-Lint 不支持该语法。 (你可能想通知维护者,除非它已经在以后的版本中得到支持。)

作为一种解决方法,如果您将其更改为:

My_Value test[] =
{   
    { .bits =
        {   
            .a = 2,
            .b = 3,
            .c = 2,
            .d = 3,
        },
    },
    { .bits =
        {   
            .a = 1,
            .b = 1,
            .c = 1,
            .d = 0,
        },
    },
};

它仍然是有效的 C(并且可以说更清晰),并且根据您刚刚在评论中写的内容,PC-Lint 接受它。

(如果您想更加明确,可以考虑添加 [0] =[1] = 指示符。)

更新:引用新评论:

Gimpel 软件的好人回应称“这 似乎是一个错误”并正在努力纠正它。

【讨论】:

  • PC-Lint 9.00k 对上面发布的第二种形式没有任何问题。我会选择这个。
  • 点对点,我刚刚用 8.00x 验证,PC-Lint 很满意,它仍然传达了代码的初衷。谢谢,Keith 并感谢 @SimeonPilgrim 为我认为仍然没有答案的问题注入了新的活力。
  • @SimeonPilgrim 和 Keith,Gimpel 软件的好心人已经回复说“这似乎是一个错误”,并且正在努力纠正它。再次感谢!
【解决方案2】:

不确定 C99 和 8.00x 支持问题,因为我安装了 9.00k。但是 9.00k 不喜欢您的联合初始化形式,但 Visual Studio 没有问题。

但对于 Jacchim Pileborg 的情况,它只会发出 Info 708: union initialization 而关闭可能更安全。

正如 cmets 中所述,您不想完全全局删除这些错误类型,因此 -e133-e10 不会解决您的问题。

所以使用 Joachim 的形式,我可以像这样使用宏来抑制它:

typedef union
{
    struct
    {
        unsigned int a : 4;
        unsigned int b : 4;
        unsigned int c : 4;
        unsigned int d : 4;
    } bits;
    unsigned short value;
} My_Value;

#define MY_UNION(A,B,C,D) /*lint -save -e708*/{{.a=(A),.b=(B),.c=(C),.d=(D)}}/*lint -restore*/

int main(void)
{
    My_Value test[] =
    {
        MY_UNION(2, 3, 2, 1),
        MY_UNION(1, 2, 3, 4)
    };

    return 0;
}

很难看,但是由于 lint 命令是匿名的,所以你没有什么可以坚持的,你必须明确地或通过宏放置内联命令。

【讨论】:

  • 谢谢,西蒙。我想我应该更详细地了解问题 2。我想在全球范围内禁止这些消息,因为它们适用于这种特殊情况。但是,这两个错误都可能有用,因此我不希望在所有情况下都禁用它们。有趣的是 9.00k 不喜欢 @JoachimPileBorg 和我的初始化......其中任何一个都应该在 C99 下工作。 +1
  • @embedded_guy 9.00k 并没有抱怨这很糟糕,但它确实有一个info 708,这样可以更安全地抑制或逐个文件抑制。真正的问题是,您所做的并不是真正的一类事物(除了 708 联合初始化),因此您无法在任何地方抑制此实例。现在您可以放入一个 MACRO,然后抑制该符号的这些错误。
  • 宏选项值得考虑。尽管我的经理已经决定在代码库中有 any lint cmets 是不可接受的,因此希望在全局范围内进行抑制。但是,我可以通过将-emacro(708, MY_UNION) 添加到我的options.lnt 文件中来解决这个问题。
猜你喜欢
  • 2013-04-19
  • 1970-01-01
  • 2013-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-19
  • 2015-10-30
  • 1970-01-01
相关资源
最近更新 更多