Edited at

MISRA C まとめ #include <misra_c.h>

More than 1 year has passed since last update.

MISRA Cは自動車業界などで利用しているC言語記述作法(coding standard)です。

MISRA C++もあります。

CERT C, CERT C++などの他の記述作法からも参照されています。

MISRA C:1998,MISRA C:2004, MISRA C:2012と三世代に進化しています。

Qiitaの記事から、書いた方の引用「」に加えて、

「補足: by @kaizen_nagoya 」という解説事項を加えています。

最後に、MISRAのコードの断片をコンパイル・実行する際に利用するヘッダファイルmisra_c.hを記載しました。

参考文献は

MISRA-C 2012 Referenceに掲載している文献の入手可能性を確認

https://qiita.com/kaizen_nagoya/items/96dc8b125e462d5575bb


C言語規格

ANSI C 1989, ISO/IEC 9899:1990, programming language, 1st

ISO/IEC/ANSI 9899:1999,programming language,2nd

ISO/IEC/ANSI 9899:2011, programming language,3rd


未定義(undefined)

CPUの機能、性能によりどのように実現すると効率的か決めるとCPU, Cコンパイラの発展に足枷となると良くないので、敢えて定義しないことを規定する。個々のCPU, Cコンパイラ処理系ごとに定義すると良い。


未規定(unspecified)

CPUの機能、性能により複数の解決方法の候補があり、どちらかを規定するとCPU, Cコンパイラの発展に足枷となると良くないので、敢えてどちらか一方にしないことを規定する。個々のCPU, Cコンパイラ処理系ごとに定義すると良い。


処理系定義(implementation definition)

処理系ごとに定義すると良い事項。未定義、未規定と異なる点は、必ず処理系で定義してプログラマに示すことが必要である事項。

ヘッダファイルなどで規定している定数、宣言などで実現している場合もある。


地域依存(locale)

処理対象、註釈(comment)として用いる、文字コード、文字フォント、自然言語の種類などにより必要な機能を定義する事項。


規則分類

必須(mandatory) 2012新設。逸脱することを想定していない。必須であっても逸脱する必要があれば、逸脱の手続きを取るとともに、MISRAに対して、逸脱から必須に変更することを要求すると良い。

必要(required)逸脱する場合には、逸脱の手続きを取る。

推奨(advisory).逸脱手順を必要としない。

「推奨」を「必要」、「必要」を「必須」として取り扱っても良い.

規則を格上げする場合には、その理由、根拠、複数のコンパイラ、複数のツールの結果を示すことが大切である。


逸脱の手続き

規則を守ることが、品質を上げることではありません。

規則が何のためにあるかを理解し、現在取り組んでいる製品と方向性が違う場合には、製品の必要な品質特性に合わせるために逸脱することが大切です。

逸脱は、ソースコードの先頭または末尾の註釈(comment)または下記のような文書を作るかは組織で決めてください。

スライド060.jpg

スライド061.jpg

スライド062.jpg

スライド063.jpg

スライド064.jpg


1 Qiitaの記事


1.1 STM32マイコンでFreeRTOSを用いてLEDを制御する(Lチカ)

https://qiita.com/46sayu/items/50b43477e7dfd55c9e21

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */


1.2 Railsアプリの例外構造パターン

https://qiita.com/tasaki-i3/items/6e90c8f037c35375c1c3

module FatalError

class InvalidArgument < Base
end
end

class Device
VALID_STATUSES = {
:deleted => 0,
:activated => 1,
}

def status=(new_status)
if new_status.is_a?(String)
super VALID_STATUSES[new_status.underscore.to_sym]
elsif new_status.is_a?(Symbol)
super VALID_STATUSES[new_status]
else
# 想定外の値が指定されたので例外にする
raise FatalError::InvalidArgument
end
end
end

「elsif句を使った場合とか、case文では必ずelse句をつけなさいという先人の教え(MISRA-C 15.7とか)があります」

補足: by @kaizen_nagoya

「MISRA C:2012 15.7 すべてのif ... else if構文は、else文で終了しなければならない」

「MISRA C:2012 16.4 すべてのswitch文は、デフォルトのラベルをもたなければならない」

が先人の教えです。


1.3 OpenVX 1.1 SC版 (Safety Critical版)の変更点

https://qiita.com/takeoverjp/items/9a3ea016c2eb30a0fd7a


1.4【社内勉強会】「リーダブルコード」の紹介

Javaコーディング規約勉強会

https://qiita.com/yuji38kwmt/items/7b1d25fc72e3fcd5d4f4

「[補足] 「関数の末尾以外の return 禁止」の発生元

MISRA-Cという「C言語のためのソフトウェア設計標準規格」が発生元らしい。」

補足: by @kaizen_nagoya

禁止ではなく、末尾以外で戻る場合には、その理由、それでいい根拠を文書化することが必須なのです。逸脱の手続きと言います。規則を守る方が信頼性が下がる場合もあります。


1.5 C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識

https://qiita.com/kaizen_nagoya/items/d89a48c1536a02ecdec9

「SWESTでも、何度もMISRA Cの講演、演習を実施しています。」


1.5.1 C++ Templates Part1 BASICS Chapter 3. Class Templates 3.2 Use of Class Template Stack stack1test.cpp

https://qiita.com/kaizen_nagoya/items/cd5fc49106fad5a4e9ed


1.6 [C][C++]の国際規格案の例題をコンパイルするときの課題7つ。

https://qiita.com/kaizen_nagoya/items/5f4b155030259497c4de


1.6.1

ISO/IEC 14288 C++ standard. bit-field

https://qiita.com/kaizen_nagoya/items/e731e6d02258fe559056


1.7どうやって MISRA C Example Suiteをコンパイルするか

https://qiita.com/kaizen_nagoya/items/fbdbff5ff696e2ca7f00


1.7.1 MISRA C.2.1 Type widening in integer promotion,(wicm3.c )

https://qiita.com/kaizen_nagoya/items/6a24db5d51efae358cfb


1.7.2 MISRA C++ 5-0-16

https://qiita.com/kaizen_nagoya/items/7df2d4e05db724752a74


1.8 CERT

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)

https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da


1.8.1 CERT C


1.8.1.1 CERT C入門(1) Rule 01. Preprocessor (PRE)

https://qiita.com/kaizen_nagoya/items/8d2cb4158ed53d5a0a28


1.8.1.2 CERT C入門(2) Rule 02. Declarations and Initialization (DCL)

https://qiita.com/kaizen_nagoya/items/8db2bf294bb66344d6df#_reference-52026d66c61fb88415c7


1.8.2 CERT C++


1.8.2.1 CERT C++入門(1) Rule 01. Declarations and Initialization (DCL)

https://qiita.com/kaizen_nagoya/items/61b3c431756fe8e6af3e


1.9 プログラミング言語教育のXYZ

https://qiita.com/kaizen_nagoya/items/1950c5810fb5c0b07be4

「TOPPERS オープンソースのMISRA C対応。」


2. 関連資料


2.1 SWESTまとめ

https://qiita.com/kaizen_nagoya/items/62e56ae151554d6200c0

https://swest.toppers.jp/SWEST17/program.html 組込み開発者におくる MISRA C


2.2 効率的なHAZOPの進め方

https://qiita.com/kaizen_nagoya/items/2b8eae196945b7976446

「物について記述してもよい 事前,事後(初期条件,境界条件)を記述 3つ以上の設計指針を使う 共用品設計(universal design),形の設計指針,言語規約(MISRA)など」


2.3 オープンソースカンファレンスの出展、セミナ、LTのすすめ

https://qiita.com/kaizen_nagoya/items/8628baa3f6e1bb500045

「名古屋アジャイル勉強会 ういろMUG Proof Cafe TOPPERS プロジェクト MISRA C愛好会 ちょけねこ友の会 などの名古屋の勉強会の集まりで出展」


2.4 TOPPERS まとめ(5つの壁のうちの一つ)

https://qiita.com/kaizen_nagoya/items/9026c049cb0309b9d451

MISRA C MISRA C研究会は、NPO法人 組込みソフトウェア管理者・技術者育成研究会(SESSAME)の作業部会(WG)


2.5 プログラマが学会・研究会で対外発表する際の9つの関門

https://qiita.com/kaizen_nagoya/items/b66b0bb7eb70b30082c8

「二上貴夫 SWESTのMISRAの解説で、少年のような目で技術を語っていた。」


2.6 SWEST20で基調講演(再演含む)してほしい人上位10人

https://qiita.com/kaizen_nagoya/items/d4d9bf953953c720361d

https://swest.toppers.jp/SWEST19/program/s3c.html 1.3 「二上貴夫 SWEST4 自動車向け組込みC言語用ガイドラインMISRA C」


3 参考文献・URL


3.1 MISRA C bulletin board

https://www.misra.org.uk/forum/index.php

英語です。日本からも多数質問をし、原書の改訂に貢献しています。


3.2 MISRA C研究会

http://www.sessame.jp/workinggroup/WorkingGroup3/index.htm


3.3 MISRA C愛好会

http://researchmap.jp/kaizen/MISRA-C/

OSCなどに出展する時の任意団体


3.4 misrac 断片コンパイル用ヘッダ


misra_c.h

/* Author, (c) Dr. Ogawa Kiyoshi*/

/* ver 1.0 January 1, 1999 */
/* ver 2.0 Feburary 2, 2005 */
/* ver 3.0 March 3, 2013 */
/* @kaizen_nagoya, http://researchmap.jp/kaizen/MISRA-C/ */
/* Purpose: macro, definition and/or information to MISRA-C Examples.*/
/* https://gcc.gnu.org/onlinedocs/gcc/Standards.html */
/* https://gcc.gnu.org/c99status.html */
/* http://www.polyomino.org.uk/computer/c/ */
#ifndef __MISRA_C__
#define __MISRA_C__

#include <float.h>
#include <iso646.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
/* define true */
#include <stddef.h>
/* define NULL */
#include <stdint.h>
/* C99: define int16_t */

#ifdef __STDC_VERSION__
#include <stdalign.h>
#include <stdnoreturn.h>
#endif

#include <stdio.h>
// #include <sys/types.h>
typedef bool bool_t;
typedef float float32_t; /* dir4.6 */
typedef long double float64_t; /* dir4.6 */

#ifdef nofreestanding
#include <string.h>
#include <stdlib.h>
#endif

#ifndef DIR4_6
#ifndef __STDC_VERSION__

typedef char char_t;
typedef unsigned char uint8_t; /* dir4.6 */
typedef unsigned short uint16_t; /* dir4.6 */
/*typedef unsigned long uint32_t;*/ /* dir4.6 */
typedef unsigned long long uint64_t; /* dir4.6 */
typedef unsigned long long uint128_t;

typedef signed char int8_t; /* dir4.6 */
typedef signed short int16_t; /* dir4.6 */
/* typedef signed long int32_t; *//* dir4.6 */
typedef signed long long int64_t; /* dir4.6 */
typedef signed long long int128_t;

typedef float float32_t; /* dir4.6 */
typedef long double float64_t; /* dir4.6 */
typedef long double float128_t; /*dir4.6 */
#endif
#endif

#ifndef NC30 /* without renesas NC30WA, manual C.3.3 predefined macro */
#define __ISO_IEC_9899_1999__
#define __int32bit__
#define PR1x(a,b) (void)printf(" "#a " = %" #b "=%x\n", a,a)
#define PR2x(a,b,c) (void)printf(" "#a " = %" #c "=%x \n " #b " = %" #c "=%x\n", a,a,b,b)
#define PR3x(a,b,c,d) PR1x(a,d),PR2x(b,c,d);

#define PR1(a,b) (void)printf(" "#a " = %" #b "\n", a)
#define PR2(a,b,c) (void)printf(" "#a " = %" #c "\n " #b " = %" #c "\n", a, b)
#define PR3(a,b,c,d) PR1(a,d),PR2(b,c,d);

#else /* for renesas NC30W only */
#define __ISO_IEC_9899_1990__
#define __int16bit__
#define PR1(a,b)
#define PR2(a,b,c)
#define PR3(a,b,c,d)
#endif
/*__STANDARD_IO__ */

#ifdef __ISO_IEC_9899_2011__
#include <stdarg.h>
#include <stdint.h>
#define PRSV() printf("ISO/IEC 9899:2011\n")
#elseif __ISO_IEC_9899_1999__
#include <stdarg.h>
#include <stdint.h>
#define PRSV() printf("ISO/IEC 9899:1999"\n)
#elseif __ISO_IEC_9899_1990__
/* #include <stdint.h> */ /*nc30wa is not supported */
typedef _bool bool_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef signed long int64_t;
typedef signed long long int128_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long uint64_t;
typedef unsigned long long uint128_t;
typedef float float32_t;
typedef double float64_t;
typedef long double float128_t;
/* macro using printf debug or not.*/
#define PRSV() printf("ISO/IEC 9899:1990\n")
#elseif __int16bit__
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef unsigned long uint64_t;
typedef unsigned long uint128_t;
#define PRSV() printf("no ISO/IEC 9899,16bit\n")
#else
/* typedef unsigned long long uint128_t;*/
#define PRSV() printf("no ISO/IEC 9899,32bit\n")
#endif

/* for each example*/

#ifdef DIR4_8
typedef struct OpaqueType *pOpaqueType;

pOpaqueType GetObject(void);
void UseObject(pOpaqueType);
#endif

#ifdef __MISRAC_6_6__
void f (uint16_t *p){
printf("uint16_t *p = %d, p = %d\n",*p,(int)p);
}
#endif /*__MISRAC_6_6__ */

#ifdef __MISRAC_6_9__
//typedef signed char int8_t;
//typedef signed short int16_t;
//typedef signed int int32_t;

#ifndef _INT64_T
#define _INT64_T
typedef signed long int64_t;
#endif

#ifndef _bool
typedef unsigned int _bool;
#endif

#endif

#ifdef __MISRAC_DIR_4_1__
#include <string.h>
#include <stdbool.h>
typedef float float32_t;
#endif

#ifdef DIR4_13
typedef struct mutex mutex_t;

struct mutex
{
unsigned int number;
unsigned char* name;
}mutex;

mutex_t n;

mutex_t mutex_lock (void)
{
return n;
}
void mutex_unlock (mutex_t m)
{
m.number = 0;
m.name = (unsigned char *)"";
return;
}

int16_t x;

#endif

#ifdef __MISRAC_RULE_1_1__
#define __zpage // zero page, 0x0000
#define __near // short address
#define __far // full address
#define zpage __zpage

int i = 1;

#endif

#ifdef R2_1

int error_handler (void){
return true;
}

#endif

#ifdef __MISRAC_RULE_2_2__
volatile uint16_t v=1;
char a[]={"123456789ABCDEF"};
char *p=a;
#endif

#ifdef __MISRAC_RULE_3_2__
bool_t b=0;
#endif

#ifdef __MISRAC_RULE_5_1__
int32_t ABC = 1;
#endif

#ifdef __MISRAC_RULE_5_2__
int32_t engine_exhaust_gas_temperature_raw=0;
#endif

#ifdef __MISRAC_RULE_5_3__
struct astruct{
int16_t m;
};

void g (struct astruct *p){printf("struct astruct *p->m = %d\n",p->m);}
#endif

#ifdef __MISRAC_RULE_5_8__
extern void foo (void);
#endif

#ifdef __MISRAC_RULE_5_9__
extern void bar1(void) ;
extern void bar2(void);
#endif

#ifdef __MISRAC_RULE_7_1__
uint16_t code[ 10 ];
#endif

#ifdef __MISRAC_RULE_7_4__
void f1 (char * s1){
PR1(s1,s);
}
void f2(const char *s2){
PR1(s2,s);
}
#endif

#ifdef __MISRAC_RULE_8_1__
xn = 0;
int16_t xc = 1;
fn(void){
return printf("fn(void);\n");
}
int16_t fc(void){
return printf("int16_t fc(void);\n");
}
void gn(char c, const k){
PR2(c,k,d);
}
void gc(char c, const int16_t k){
PR2(c,k,d);
}
#endif

#ifdef __MISRAC_RULE_8_2__

#endif

#ifdef R8_4
extern uint16_t var1; // 宣言
extern void func1( uint16_t var1 );
extern void func2( uint16_t var1 );
#endif

#ifdef __MISRAC_RULE_8_4__
extern int16_t count;

extern void func1 (void);
extern void func2 (int16_t x, int16_t y);
extern void func3 (int16_t x, int16_t y);

#endif

#ifdef __MISRAC_RULE_8_5__
extern int16_t a;
#endif

#ifdef __MISRAC_RULE_8_6__
void f1(void);
void f2(void);
#endif

#ifdef __MISRAC_RULE_8_11__
int32_t array1[10]={0,1,2,3,4,5,6,7,8,9};
int32_t array2[]={9,8,7,6,5,4,3,2,1,0};
#endif

#ifdef __MISRAC_RULE_8_13__
char last_char (const char * const s);
// uint16_t first( const uint16_t a[5]);
#endif

#ifdef __MISRAC_8_14__
volatile bool_t b=true;
struct s{
uint16_t count;
uint16_t a[ 10 ];
};
struct s sps = {
0,
{0,1,2,3,4,5,6,7,8,9}
};
struct s * sp;
char *p="Control Statement Expressions\n";
#endif

#ifdef R11_1
void f(int16_t n){
// printf("%d\n",n);
}
#endif

#ifdef __MISRAC_RULE_11_1__
void f(int16_t n){
PR1(n,d);
}
#endif

#ifdef R11_2
void f(int16_t n){
// printf("%d\n",n);
}
#endif

#ifdef R11_3
uint32_t read_value ( void ){
return true;
}
void print ( uint32_t n ){
PR1(n,d);
}
#endif

#ifdef __MISRAC_RULE_11_3__
uint32_t read_value ( void ){
return true;
}
void print ( uint32_t n ){
PR1(n,d);
}
#endif

#ifdef R11_4
void print ( uint16_t n ){
PR1(n,d);
}
#endif

#ifdef __MISRAC_RULE_11_9__
void f ( uint8_t *p ){
if (NULL == p){
PR1(NULL,d);
} else {
PR2(*p,NULL,d);
}
}
#endif

#ifdef __MISRAC_RULE_12_1__
int8_t f(int8_t a, int8_t b){
return a+b;
}
#endif

#ifdef __MISRAC_RULE_12_3__
void f(int8_t a, int8_t b){
PR2(a,b,d);
}
#endif

#ifdef __MISRAC_RULE_13_1__
void p ( uint16_t a[ 2 ] ){
PR2(a[0],a[1],d);
}
#endif

#ifdef __MISRAC_RULE_13_2__

#endif

#ifdef R14_1
uint32_t read_u32(void){
static uint32_t i = 14;
return --i;
}
float32_t read_float32(void){
static float32_t f = 0;
return ++f;
}
#endif

#ifdef __MISRAC_RULE_14_4__
bool_t flag= true;
#endif

#ifdef __MISRAC_RULE_17_3__
double power (double d, int n){
return (double)d*n;
}
#endif

#ifdef R17_6
#define TEN 10U
uint16_t v1[TEN]={0,1,2,3,4,5,6,7,8,9};
uint16_t v2[TEN+TEN]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
uint16_t v3[TEN+TEN+TEN]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30};

uint16_t t2(uint16_t n, uint16_t a[20]) {
uint16_t i;
uint16_t sum=0U;
for(i = 0U; i < n; ++i){
sum = sum + a[i];
}
return sum;
}
uint16_t t(uint16_t n, uint16_t a[]) {
uint16_t i;
uint16_t sum=0U;
for(i = 0U; i < n; ++i){
sum = sum + a[i];
}
return sum;
}
#endif

#ifdef __MISRAC_RULE_17_6__
uint16_t v1[10]={0,1,2,3,4,5,6,7,8,9};
uint16_t v2[20]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
#endif

#ifdef __MISRAC_C_2_1_
#ifndef __STANDARD_IO__
/* without renesas NC30W */
#define PR(a,b,c,d,e) printf("%" #a " + %" #a "= %" #a ", %" #b "\n", c, d, c + d, e)
#define PRC(a,b,c,d,e,f) printf("%" #a" + %" #a " = %" #a ", %" #b "\n", c, d, (f) c + d, e)
#define PRT(a,b,c,d,e,f) PR(a,b, c, d, e); e = c + d;PR(a,b, c, d, e); e = (f) c + d;
/*printf(#e"= %llu ",e)*/;PRC(a,a, c, d, e, f);PRC(a,b, c, d, e, f)
#else
/* for renesas NC30W only */
#define PR(a,b,c,d,e)
#define PRC(a,b,c,d,e,f)
#define PRT(a,b,c,d,e,f)
#endif
/*__STANDARD_IO__ */
#endif
/* __MISRAC_C_2_1_ */

#endif /* __MISRAC__ */



4 関連文献

どうやって MISRA Example Suiteをコンパイルするか

https://qiita.com/kaizen_nagoya/items/fbdbff5ff696e2ca7f00

MISRA C.2.1 Type widening in integer promotion,(wicm3.c )

https://qiita.com/kaizen_nagoya/items/6a24db5d51efae358cfb

MISRA-C 2012 Referenceに掲載している文献の入手可能性を確認

https://qiita.com/kaizen_nagoya/items/96dc8b125e462d5575bb

MISRA C まとめ #include

https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9

MISRA C++ 5-0-16

https://qiita.com/kaizen_nagoya/items/7df2d4e05db724752a74


5 文献履歴

1.0 初稿 20180316

1.01 見出し分類 20180317

1.02 10項目追記 20180322