メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C: Rec.DCL07-C

適切な型情報を関数宣言子に含める

説明

ルール定義

適切な型情報を関数宣言子に含めます。1

Polyspace 実装

ルール チェッカーは以下の問題をチェックします。

  • 型が異なる関数ポインター間のキャスト

  • 暗黙的に宣言された関数

すべて展開する

問題

この問題は、関数へのポインターと他の型の間で変換を実行する場合に発生します。

Polyspace® はこのルールをチェックする際に、明示的なキャストと暗黙的なキャストの両方を考慮します。ただし、NULL または (void*)0 からのキャストはこのルールに違反しません。

リスク

ルールにより以下の 2 つの変換は禁止されています。

  • 関数ポインターから他の型への変換。この変換により未定義の動作が発生します。

  • 関数ポインターから別の関数ポインターへの変換 (それぞれの関数ポインターが異なる引数と戻り値の型をもつ場合)。

    互換性のない型のポインターを介した関数呼び出しは未定義の動作になるため変換は禁止されています。

例 - 2 つの関数ポインター間のキャスト
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 型のポインター fp1fp32 型にキャストされる。関数ポインターの fp16 型と fp32 の引数の型が異なる。

  • 整数が fp16 型にキャストされる。

関数ポインター fp1fp2NULL にキャストされる場合、ルールに違反しません。

問題

この問題は、関数を暗黙的に宣言する場合に発生します。

リスク

暗黙的な宣言は、関数を宣言または定義する前に呼び出す場合に発生します。関数を呼び出す前に明示的に宣言すると、コンパイラにより引数と戻り値の型を宣言内のパラメーター タイプと一致させることができます。暗黙的な宣言が発生する場合、コンパイラにより引数と戻り値の型が仮定されます。たとえば、戻り値の型として 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.