メインコンテンツ

MISRA C++:2008 Rule 16-0-6

In the definition of a function-like macro each instance of a parameter shall be enclosed in parentheses unless it is used as the operand of # or ##.

説明

ルール定義

In the definition of a function-like macro each instance of a parameter shall be enclosed in parentheses unless it is used as the operand of # or ##. 1

根拠

関数形式のマクロを呼び出すと、コンパイラがマクロのパラメーターをトークンで置き換えて、マクロを展開します。コンパイラは、この展開したマクロをコードに代入します。この展開と代入のプロセスでは、演算の優先順位は考慮されません。関数形式のマクロは、そのパラメーターが小かっこで囲まれていない場合、予期せぬ結果をもたらす可能性があります。たとえば、次の関数形式のマクロがあるとします。

#define dustance_from_ten(x) x>10? x-10:10-x
このマクロは 10 からの数値の距離を測定するよう意図されています。このマクロを引数 (a-b) を使用して呼び出すと、マクロが次のように展開されます。
a-b>10: a-b-10:10-a-b
10-a-b は、意図された距離 10-(a-b) ではなく 10-(a+b) と等価になります。この予期せぬ動作はエラーやバグの原因になる可能性があります。このような予期せぬ動作を回避するには、関数形式のマクロのパラメーターを小かっこで囲みます。

パラメーターが # または ## のオペランドとして使用されている場合は、このルールの例外となります。

Polyspace 実装

関数形式のマクロのパラメーターが小かっこで囲まれていない場合、Polyspace® はこのマクロ定義にフラグを設定します。パラメーターの前に演算子 .->、または文字 ### がある場合、Polyspace は小かっこで囲まれていないパラメーターにフラグを設定しません。

トラブルシューティング

ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#include<iostream>
#include<cmath>
#define abs(x) (x>0) ? x:-x //Noncompliant

double foo(double num1, double num2){
	return log(abs(num1-num2));
}

int main(){
	std::cout<<foo(10,10.5);
}

この例では、foo(10,10.5) を呼び出すと、その出力は log(0.5) または -0.69 になることが想定されます。abs のパラメーターは小かっこで囲まれていないため、出力は想定とは異なる log(-20.5) または NaN になるため、バグにつながる可能性があります。Polyspace は、この関数形式のマクロ定義にフラグを設定します。

チェック情報

グループ: Preprocessing Directives
カテゴリ: 必要

バージョン履歴

R2013b で導入


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.