Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What are the problem?

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

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チカ)

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

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

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版)の変更点

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

Javaコーディング規約勉強会
https://qiita.com/yuji38kwmt/items/7b1d25fc72e3fcd5d4f4

「[補足] 「関数の末尾以外の return 禁止」の発生元
MISRA-Cという「C言語のためのソフトウェア設計標準規格」が発生元らしい。」

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

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

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

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

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

1.6.1

ISO/IEC 14288 C++ standard. bit-field
https://qiita.com/kaizen_nagoya/items/e731e6d02258fe559056

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

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

1.7.2 MISRA C++ 5-0-16

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)

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

1.8.2 CERT C++

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

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の進め方

「物について記述してもよい 事前,事後(初期条件,境界条件)を記述 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つの関門

「二上貴夫 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研究会

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

docker(200) Misra Example Suite at docker コンパイル完了までの道のり
https://qiita.com/kaizen_nagoya/items/71f04a0204d5a1114577

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:2012追加文書
https://qiita.com/kaizen_nagoya/items/d08b2ae495b136f9638c

MISRA C まとめ #include
https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9

MISRA C 2012のTechnical Corrigendum 1の21.X訂正意見はほとんど日本からだった件
https://qiita.com/kaizen_nagoya/items/152c1de26b0831c02f41

Autosar Guidelines C++14 example code compile list(1-169)名古屋のIoTは名古屋のOSで https://qiita.com/kaizen_nagoya/items/8ccbf6675c3494d57a76

MISRA C++ 5-0-16
https://qiita.com/kaizen_nagoya/items/7df2d4e05db724752a74

言語規格、コーディング標準の使い方
https://qiita.com/kaizen_nagoya/items/01256365b82666e101aa

5 文献履歴

ver. 1.00 初稿 20180316
ver. 1.01 見出し分類 20180317
ver. 1.02 10項目追記 20180322
ver. 1.03 URL追記 20201228

<この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。>

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
8
Help us understand the problem. What are the problem?