主要内容

CERT C:Rec.DCL07-C

Include the appropriate type information in function declarators

描述

规则定义

Include the appropriate type information in function declarators.1

Polyspace 实现

规则检查项会检查以下问题:

  • 不同类型的函数指针之间的转换

  • 隐式声明的函数

示例

全部展开

问题

当您在一种函数指针与任何其他类型之间进行转换时会出现此问题。

Polyspace® 在检查此规则时,会同时考虑显式转换和隐式转换。但从 NULL(void*)0 进行的转换并不违反此规则。

风险

该规则禁止以下两种转换:

  • 从函数指针到其他任何类型的转换。这种转换会导致未定义行为。

  • 从一个函数指针到另一个函数指针的转换(如果函数指针具有不同的参量类型和返回类型)。

    这种转换会被禁止,因为通过类型不兼容的指针调用函数会导致未定义行为。

示例 - 两个函数指针之间的转换
typedef void (*fp16) (short n);
typedef void (*fp32) (int n);

#include <stdlib.h>                     /* To obtain macro  NULL */

void func(void) {   /* Exception 1 - Can convert a null pointer 
                     * constant into a pointer to a function */
  fp16 fp1 = NULL;                 /* Compliant - exception  */
  fp16 fp2 = (fp16) fp1;           /* Compliant */
  fp32 fp3 = (fp32) fp1;           /* Non-compliant */
  if (fp2 != NULL) {}              /* Compliant - exception  */
  fp16 fp4 = (fp16) 0x8000;        /* Non-compliant - integer to 
                                    * function pointer */}

在此示例中,当出现以下情况时便会违反规则:

  • 类型为 fp16 的指针 fp1 转换为类型 fp32。函数指针类型 fp16fp32 具有不同的参量类型。

  • 整数转换为 fp16 类型。

当函数指针 fp1fp2 转换为 NULL 时,不违反规则。

问题

当您隐式声明函数时,会出现此问题。

风险

如果在声明或定义函数之前调用函数,会发生隐式声明。如果在调用函数之前显式声明函数,编译器可以将参量和返回类型与声明中的参数类型进行匹配。如果发生隐式声明,编译器会对参量和返回类型进行假设。例如,它会假定返回类型为 int。这些假设可能与预期不符,并导致不期望的类型转换。

示例 - 调用前未声明的函数
#include <math.h>

extern double power3 (double val, int exponent);
int getChoice(void);

double func() {
    double res;
    int ch = getChoice();
    if(ch == 0) {
        res = power(2.0, 10);    /* Non-compliant */
    }
    else if( ch==1) {
        res = power2(2.0, 10);   /* Non-compliant */
    }
    else {
        res = power3(2.0, 10);   /* Compliant */
        return res;
    }
}

double power2 (double val, int exponent) {
    return (pow(val, exponent));
}

在此示例中,当代码中调用未声明的函数时,便违反了此规则。即使代码的后面部分存在函数定义,也会出现违规。

如果在代码中调用某个函数之前已声明该函数,则不会违反此规则。如果函数定义存在于另一个文件中,且仅在链接阶段可用,则可以通过以下方式之一声明该函数:

  • 在当前文件中使用 extern 关键字声明函数。

  • 在头文件中声明函数,然后在当前文件中包含此头文件。

检查信息

组:Rec.02.声明和初始化 (DCL)

版本历史记录

在 R2019a 中推出


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.