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

时间:2014-07-29 12:06:37

标签: c++ c clang

我想确保这种类型的代码

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在2个函数声明之间没有区别:

|-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似乎告诉了相反的结果。

有没有办法区分?

3 个答案:

答案 0 :(得分:10)

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

void f1 (int32_t p[10]);

完全相同
void f1 (int32_t* p);

在两种情况下,参数都是指针。任何地方都没有尺寸信息。

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

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

此签名与示例中显示的f1f2不同。

答案 1 :(得分:1)

  

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

你的猜测错了。

  

有没有办法区分?

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

答案 2 :(得分:1)

我认为你从错误的一端攻击这个问题。功能的声明是等效的,但这不是问题,因为您之后的规则适用于呼叫站点。在调用站点,您当然知道该数组被传递给一个带有指针的函数,并且不会在另一个参数中获取数组大小。从调用网站的角度来看,f1f2调用在语义上都是相同的。他们同样安全或不安全。

C标准并不要求编译器在将参数传递给函数时保留数组边界信息。如果函数的参数声明中有任何数组边界,则它们仅供人类使用。根据MISRA,f1f2电话完全相同,而且它们都是错误的。您需要显式传递指针和数组大小。

如果您希望对使用指针或小于给定大小的数组调用f1进行特殊诊断,则必须修改解析器并向AST添加自定义注释。然后,您的分析仪可以获取该信息。

对于任何这些都没有任何意义,当静态代码分析表明参数被索引超过f1内的边界时,您还需要添加诊断。