BETA

C言語の処理系定義動作サンプルコード(書き途中)

投稿日:2019-10-10
最終更新:2019-10-24

毎日ちびちびと記述予定(書ききるまではログのほうが良いのかな…?)
マサカリ大歓迎です(誰か変わりに書いてくださってもいいのよ?)

※日本語力が嫁の飯マズレベルで壊滅的なので解釈に誤りがある可能性があります。

【参考】
処理系定義の動作の一覧:http://www.c-lang.org/detail/implementation_defined_behavior.html
JIS C言語規格(規格参照時は主にこちらを用いています):https://kikakurui.com/x3/X3010-2003-01.html
C99ドラフト:http://www.open-std.org/Jtc1/sc22/wg14/www/docs/n1124.pdf
非常に参考になりました。深く感謝いたします。

3.6 バイト辺りのビット数

#include <stdio.h>  
#include <limits.h>  
int main(){  
    printf("%d\n",CHAR_BIT);    // 1バイト辺りのbit数は任意  
}  

3.10 処理系定義の部分集合に属する診断メッセージ

#include <stdio.h>  
int main(){  
    int a = 'ab'; // 規格6.4.4.4 により処理系定義。この文に対する診断メッセージの出力及び内容は任意  
}  

5.1.1.2 コメントアウト、改行文字、空白文字並びの置き換え

#include <stdio.h>  
#define A(a) #a                             
int main(){  
    puts(A(        // 空白文字を一纏めにしてもしなくても良いし  
                   // 改行文字を無かったことにしても問題ない  
            /*コメント部分を空白文字に置き換えるかどうかも任意*/         ));  
}  

5.1.1.2 マルチバイト文字とソース文字集合のマッピング

#include <stdio.h>  
int main(){  
    const char * str = "あいう";  //マルチバイト文字を任意のソース文字集合に置き換えても良い(フェーズ1)  
    puts(str);     
}  

※ ソース文字集合に関しては「5.2.1 文字集合」を参照
※ フェーズに関しては「5.1.1.2 翻訳フェーズ」を参照

5.1.1.2 文字定数及び文字列リテラルの実行文字集合への変換時に、対応する文字が無かった場合の対応

#include <stdio.h>  
int main(){  
    const char * str = "えおか"; // 実行文字集合へ変換できない要素を任意の要素に変換しても良い(フェーズ5)  
    const char * strあ = "きくけ"; //※文字定数、文字リテラル以外は非変換対象(変数名「strあ」はこの時変換対象ではない)  
    printf("%s,%s\n",str,strあ);  
}  

※ 実行文字集合に関しては、上の項目と同じく「5.2.1 文字集合」を参照

5.1.1.3 制約違反に対するメッセージ

#include <stdio.h>  
int main(){  
    int i;  
    char i;  //制約違反の場合は必ずエラーを出す必要があるが内容は任意  (このコードは規格6.7により制約違反かつ未定義)  
}  

※未定義動作については「3.4.3 未定義の動作」「4 規格合致性」
 制約については「3.8 制約」を参照。

5.1.2.1 フリースタンディング環境下でのプログラム開始関数

static void _init(){  
    /* 何かしらの開始処理 */  
}  
static void _exec(){  
    /* 何かしらの処理 */  
}  
static void _exit(){  
    /* 何かしらの終了処理 */  
}  

void _start(){   //フリースタンディング環境下でのプログラム開始時関数の名前及び型は任意  
    _init();  
    _exec();  
    _exit();  
}  

5.1.2.1 フリースタンディング環境下でのプログラム終了時処理

void _start(){  
    //プログラム終了時に何を行うかは任意  
}  

5.1.2.2.1 main関数の定義方法

void main(){    //処理系定義の方法で定義  
}  

※ main関数は

  1. int main(void)
  2. int main(int argc, char *argv[])
  3. 上2つと等価な定義(int main(int argc,char **argv)等)
  4. 上3つのどれでもない処理系定義の型

のどれかを使用して定義する事が出来る
詳しくは「5.1.2.2.1 プログラム開始処理 」を参照

5.1.2.2.1 argv内のポインタが指し示す文字列の値

#include <stdio.h>  
int main(int argc,char *argv[]){  
    for(char **itr = argv;*itr != NULL;++itr){  
        puts(*itr); // 文字列の中身は任意  
    }  
}  

5.1.2.3 対話型装置

#include <stdio.h>  
int main(){  
    char buf[] = "hogehoge";  
    FILE *fp = fopen("aaa","w"); //fpが指し示すユーザインタフェースがどのような物であるかは任意  
    fwrite(buf,sizeof(char),sizeof(buf) / sizeof(char),fp);  
}  

5.2.1 ソース文字集合,実行文字集合における基本文字集合以外の要素

#include <stdio.h>  
int main(){  
    char *@`$あ = "@`$あ"; //基本文字集合以外の要素がどのような物かは任意(マルチバイト文字を含んでいても良い)  
    puts(@`$あ);   
}  

5.2.2 逆斜線(バックスラッシュ)表記に格納される値

#include <stdio.h>  
int main(){  
    const char *str = "\a\b\f\n\r\t\v"; //各逆斜線表記を処理系定義の値に変換して格納する(1文字辺り)  
    while(*str != '\0'){  
        printf("%d,",*str);  
        ++str;  
    }  
}  

6.2.5 実行基本文字集合以外の要素の値

#include <stdio.h>  
int main(){  
    char c = '@'; // 処理系任意の値(ただしcharで表現できる範囲内)  
    printf("%d\n",c);  
}  

6.2.5 charがsignedかunsignedか

#include <stdio.h>  
int main(){  
    printf("%d\n",0 < (char)-1); //signedとunsignedのどちらかは任意  
}  

6.2.6.2 符号付き整数型の表現方法

#include <stdio.h>  
#include <stdint.h>  
int main(){  
    int16_t val = -1;  
    for(unsigned int i=32768;i;i >>= 1){  
        printf("%d",(val & i) ? 1 : 0); //1の補数,2の補数,符号と絶対値等どの表現を利用するか任意  
    }  
    puts("");  
}  

6.2.6.2 所定の値を通常の値/トラップ表現のどちらで扱うか

#include <stdio.h>  
#include <stdint.h>  
int main(){  
    // 以下2つの値をトラップ表現/通常の値のどちらで採用されるかは任意  
    int16_t val = 0x8000;   //【2の補数の場合】 符号ビットが1でその他が0の値  
    int16_t val2 = 0xFFFF;   //【トラップ表現/1の補数の場合】符号ビット含めた全ビットが1の場合(通常として扱う場合規格上,負の0(negative zero)となる)  
    printf("%d\n",val);  
    printf("%d\n",val2);  
}  

※1. トラップ表現は不定の値として扱われる。(3.17.2不定の値 を参照)
※2. 負の0として扱われる値が生成されるタイミングは規格で定められたタイミングでなければならない
詳しくは「6.2.6.2」参照

6.4.4.4 単純文字定数に複数文字もしくはマルチバイト文字が含まれていた場合の値

#include <stdio.h>  
int main(){  
    int a = 'ab',b = 'あ';    //この時の値は任意  
    printf("%d,%d,%d\n",a,b);  
}  

6.4.4.4 ワイド文字定数に、複数のマルチバイト文字,実行拡張文字集合に含まれない文字,逆斜線表記が含まれた場合の値

#include <wchar.h>  
#include <stdio.h>  
#include <wchar.h>  
int main(){  
    wchar_t a = L'あい',b = L'あ',c=L'\n'; //この時の値は任意    
    printf("%d,%d,%d\n",a,b,c);  
}  

6.4.4.4 多バイト文字をワイド文字に対応付ける際に使用するロケール

#include <wchar.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <locale.h>  
int main(){  
    char str[] = "あ";  
    wchar_t c;  
    setlocale(LC_CTYPE,"ja_JP.UTF-8");    //使用するロケールは任意  
    int result = mbtowc(&c,str,sizeof(str));    //対応方法はmbtowcにて定義する  
    printf("%d\n",result);  
    printf("%lc\n",c);  
}  

6.5.3.4 sizeof演算子の結果値

#include <stdio.h>  
int main(){  
    size_t s1 = sizeof(int);    //返却される値は処理系定義(組込型サイズ自体が処理系定義な為)  
}  
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@kizulの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!