0

“不!” 是正确的答案,但不幸的是它不是我需要的。

如果我做:

size_t array_size = func_that_calc_array_size();
char *foo = new char[array_size];
if (array_size > 42)
    foo[42] = 'X';

这都是完全合法的,但我的 MISRA C++ 代码检查器在 上给出了错误 5-0-15 foo[42],它表示“数组索引应该是指针算术的唯一形式”。这个问题实际上之前已经被问过,但是问题和答案错过了一个关键问题,即文档进一步指出:

数组索引只能应用于定义为数组类型的对象。

如果您查看文档(通过搜索“misra c++ 2008 pdf”可以找到可疑的盗版副本),它有一个类似于以下内容的示例:

void my_fn(uint8_t *p1, uint8_t p2[])
{
    p1[5] = 0; // Non-compliant - p1 was not declared as array
    p2[5] = 0; // Compliant
}

因此,基本上代码检查工具将声明与用法相匹配。有没有办法将指针转换为数组?


在我们的真实示例中,我们使用的是 OpenCV uchar *cv::Mat::ptr(),因此我们不能只保留一个足够大的数组。

4

2 回答 2

1

该规则的有效性令人怀疑。在示例中,p1p2具有完全相同的类型:它们都是指针。

如果p2确实符合规则,那么解决方法就是引入一个函数,这样就可以利用函数-参数-数组-指针-调整。这是一个带有 lambda 的示例,但您也可以使用常规函数:

char *foo = new foo[array_size];
if (array_size > 42)
    [](char foo[]) {
        foo[42] = 'X';
    }(foo);

C++20 引入了std::span,这似乎是解决问题的方法:

std::span foo_span{foo, array_size};
if (array_size > 42)
    foo_span[42] = 'X';

这使用了下标运算符的类重载,而不是指针下标,因此它似乎符合规则。std::span在不违反 MISRA 的情况下可能无法实现,但标准库中的许多其他内容也是如此,所以我怀疑这不是问题。


在我们的真实示例中,我们使用的是 OpenCV uchar *cv::Mat::ptr(),因此我们不能只保留一个足够大的数组。

也许要遵循规则的精神,而不是字母,您应该将 a 传递给cv::Mat&函数而不是char*.

PS我怀疑OpenCV不符合MISRA,所以如果程序必须符合MISRA,取决于它可能不是最好的选择。

于 2019-06-03T02:18:57.423 回答
1

我认为这里问题的根源是char *foo = new char[array_size];. MISRA 检查器可以假设这不是一个数组,因为所有动态内存分配都被禁止。

您可以尝试查看在编写时是否遇到相同的错误,char array[10]={0}; char* foo = array;因为您可以将其视为误报工具错误。

该规则的目的和基本原理是禁止形式*(x + i)而不是x[i]. 没有其他的。该规则不会阻止对[]指针操作数的使用。

然而,一些 MISRA 规则已经到位,以确保所有指针运算都使用指向同一数组的操作数完成,以防止未定义的行为。

MISRA-C:2004 和 MISRA-C++:2008 也有一些奇怪的、模糊的要求,即函数参数应声明为char param[]而不是char* param,但由于这是荒谬的,所有关于数组样式索引的讨论都在 MISRA-C:2012 中删除。

(实际上在 C 或 C++ 中没有“数组样式索引”之类的东西,请参阅指针支持“数组样式索引”吗?

于 2019-06-03T08:01:31.597 回答