将指向 X 的指针转换为 X 的数组
Converting a pointer to X to an array of X
"Don't!"是正确答案,可惜不是我需要的。
如果我这样做:
size_t array_size = func_that_calc_array_size();
char *foo = new char[array_size];
if (array_size > 42)
foo[42] = 'X';
这完全合法,但我的 MISRA C++ 代码检查器在 foo[42]
上给出错误 5-0-15,表示 "Array indexing shall be the only form of pointer arithmetic"。这个问题有,但是问题和答案遗漏了一个关键问题,即文档进一步指出:
Array indexing shall only be applied to objects defined as an array type.
如果您查看文档(可以通过搜索 "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()
,所以我们不能只保留一个足够大的数组。
该规则的有效性非常可疑。在示例中,p1
和 p2
具有完全相同的类型:它们都是指针。
如果p2
确实符合规则,那么解决办法就是引入一个函数,这样就可以利用function-argument-array-to-pointer-adjustment了。这是一个使用 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';
这使用了下标运算符的 class 重载,而不是 pointer-subscript,因此看起来符合规则。 std::span
在不违反 MISRA 的情况下可能无法实现,但标准库中的许多其他内容也是如此,所以我怀疑这不是问题。
In our real example, we are using OpenCV's uchar *cv::Mat::ptr()
, so we can't just reserve a large-enough array.
也许遵循规则的精神,而不是字母,您应该将 cv::Mat&
传递给函数而不是 char*
。
P.S。我怀疑 OpenCV 不符合 MISRA,因此如果程序必须符合 MISRA,依赖它可能不是最好的选择。
我认为问题的根源在于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++ 中没有 "array style indexing" 这样的东西,参见 )
"Don't!"是正确答案,可惜不是我需要的。
如果我这样做:
size_t array_size = func_that_calc_array_size();
char *foo = new char[array_size];
if (array_size > 42)
foo[42] = 'X';
这完全合法,但我的 MISRA C++ 代码检查器在 foo[42]
上给出错误 5-0-15,表示 "Array indexing shall be the only form of pointer arithmetic"。这个问题有
Array indexing shall only be applied to objects defined as an array type.
如果您查看文档(可以通过搜索 "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()
,所以我们不能只保留一个足够大的数组。
该规则的有效性非常可疑。在示例中,p1
和 p2
具有完全相同的类型:它们都是指针。
如果p2
确实符合规则,那么解决办法就是引入一个函数,这样就可以利用function-argument-array-to-pointer-adjustment了。这是一个使用 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';
这使用了下标运算符的 class 重载,而不是 pointer-subscript,因此看起来符合规则。 std::span
在不违反 MISRA 的情况下可能无法实现,但标准库中的许多其他内容也是如此,所以我怀疑这不是问题。
In our real example, we are using OpenCV's
uchar *cv::Mat::ptr()
, so we can't just reserve a large-enough array.
也许遵循规则的精神,而不是字母,您应该将 cv::Mat&
传递给函数而不是 char*
。
P.S。我怀疑 OpenCV 不符合 MISRA,因此如果程序必须符合 MISRA,依赖它可能不是最好的选择。
我认为问题的根源在于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++ 中没有 "array style indexing" 这样的东西,参见