C
coding
TOPPERS
MISRA
名古屋のIoTは名古屋のOSで

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