Clang把int32_t *p和int32_t p[10]之间的区别存储在哪里?

5

我想确认一下这种类型的代码

void f1 (int32_t p[10]);
void f2 (int32_t *p);
void b ()
{
    int_32_t a[10];
    f1(a);
    f2(a);
}

当使用f2()时,由于可能会丢失数组边界的信息,因此在编码时不会发生这种情况。这是MISRA标准规则之一。

但AST-dump在两个函数声明之间没有区别:

|-FunctionDecl 0x2204140 <test.cpp:3:1, col:23> f1 'void (int32_t *)'
  | -ParmVarDecl 0x2204040 <col:10, col:22> p 'int32_t *'
|-FunctionDecl 0x2204280 <line:4:1, col:20> f2 'void (int32_t *)'
  | -ParmVarDecl 0x2204200 <col:10, col:19> p 'int32_t *'

我猜Clang确实会记录数组的大小(10),但是AST-dump似乎告诉我们相反的情况。有没有什么方法可以区分这两种情况呢?

9
不,这句话的意思是第一个被调整以适应第二个。 - chris
1
@Cyber:这不是关于我能用什么;)。我正在编写一个代码分析器,其中一个规则就是我在问题中提到的那个。我想确保我的分析器用户不会将数组作为仅要求指针的函数的参数。 - Marc-O
2
需要澄清的是:在 C 或 C++ 中,f1f2 数组的大小均未知。这使得这个问题有些无意义。 - juanchopanza
2
@Marc-O,根据您的评论,MISRA指南表示您应该声明函数以获取对数组的_reference_,这将保留大小信息。在您最初的问题中,数组被传递为指针,这不会保留大小信息。int32_t(&p)[10]p声明为大小为10的数组的引用。 - Jonathan Wakely
1
你可能需要为这个特定的情况编写自己的解析器和语义分析器(或者在构建AST之前从clang中获取这些信息)。 - juanchopanza
显示剩余7条评论
3个回答

10

这个问题似乎基于一个误解。这个函数声明

void f1 (int32_t p[10]);

完全相同

void f1 (int32_t* p);

这个参数在两种情况下都是指针。没有任何地方保留大小信息。

请注意,在C++中,您可以拥有引用特定大小数组的函数参数。例如,

void f3(int (&p)[10]);

这个签名与您的示例中显示的f1f2不同。


编译器会保留大小信息以显示错误消息,但一旦编译完成,这些信息就会丢失。不是吗? - PaperBirdMaster
2
@PaperBirdMaster 我怀疑这一点。我从未见过编译器这样做,因为在语言层面上没有大小信息。如果你有反例,我很感兴趣知道。 - juanchopanza
我没有我猜测的例子,只是你知道的:一个猜测。 - PaperBirdMaster
即使是我们中最好的人有时也会犯错 - http://www.tedunangst.com/flak/post/how-to-screw-up-crypto-the-easy-way(纯老式C,而不是C ++) - loreb
@loreb 哈哈,这是初学者的错误!但我想知道谁认为在 C 语言中允许这种虚假的数组参数语法是个好主意。我相信它造成的伤害远大于好处。 - juanchopanza

1

我猜Clang确实记录了数组的大小(10),但AST-dump似乎表明相反。

你的猜测是错误的。

有什么区别的方法吗?

没有。根据C和C++的规则,没有区别。请参见http://www.c-faq.com/aryptr/aryptrparam.html


1
我认为你从错误的角度解决了问题。虽然函数的声明是等价的,但这不是问题,因为你所需要的规则适用于调用点。在调用点上,你肯定知道数组被传递给一个接受指针而不是在另一个参数中传递数组大小的函数。从调用点的角度来看,f1f2调用在语义上是相同的。它们是同样安全或不安全的。
C标准不要求编译器在将参数传递到函数时保留数组边界信息。如果函数参数声明中有任何数组边界,则它们仅供人类消费。根据MISRA,f1f2调用完全相同,并且它们都是错误的。你需要显式地传递指针和数组大小。
如果你想为当f1被调用时传入的指针或小于给定大小的数组添加特殊诊断,那么你需要修改解析器并向AST添加自定义注释。然后你的分析器可以获取这些信息。
要使这一切有意义,您还需要在静态代码分析指示参数超出f1范围时添加诊断信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接