-
プラグマ(
Pragmas) -
コンパイラ へ特別な情報を渡したり、 言語 の拡張を追加するための・・・
pragma( 識別子 ); pragma( 識別子, ArgumentList );
ちょっと特殊な Keyword です。
- msg
-
定義済みプラグマで、コンパイル中 にメッセージを表示します。
コンパイルされると、
pragma( msg, ... );msgの後の引数が表示されます。import std.stdio; void main(){ // コンパイル メッセージ pragma( msg, "Welcome Beginner\n", " by pragma msg" ); // 実行メッセージ writeln( "Welcome Beginner\n", " by writeln" ); }
コンパイルして実行
D:\Pen-Jr\My Programs\types>dmd test Welcome Beginner by pragma msg D:\Pen-Jr\My Programs\types>test Welcome Beginner by writeln
実行時には無関係で、コンパイル時に決まる 定数 に限りますが、ほとんど
writelnと同じ様に使えます。-
-c指定コンパイル -
pragmaは組み込みですからimportが不要で、実行する必要もありませんから エントリーポイント が必要ありません。コンパイル時に
-cを指定すれば、コンパイルだけで実行ファイルは作りませんから、軽量モジュール を、
/* ^ import も main関数もなし ^ ^ これだけでコンパイル */ pragma( msg, "Welcome Beginner\n", " by pragma msg" );
-cを付けてコンパイル。D:\Pen-Jr\My Programs\types>dmd test -c Welcome Beginner by pragma msg
オブジェクトファイル(
test.obj)だけ出力して、終了します。指定なしでコンパイルすると、
D:\Pen-Jr\My Programs\types>dmd test Welcome Beginner by pragma msg OPTLINK (R) for Win32 Release 8.00.8 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html OPTLINK : Warning 23: No Stack OPTLINK : Warning 134: No Start Address
リンカー に叱られます。
- コンパイル中のメッセージで何すんの?
- メタプログラム のデバッグなんかには使いますが、実行時には関係ないですからほとんど出番はありません。
- リアルな言語仕様
-
言語仕様はリファレンスだけでなく、コンパイラに直接聞いて調べることが出来ます。
その場合も、
pragmaでなければ得られないようなことはほとんどなく、またpragmaではコンパイル時に決まる情報以外は得られません。実行させる手間など知れてますし、実行させた方がより多彩な方法で調べることも出来ますが、型 などの言語仕様を見る時には、あえて使う意味もあります。
- 実行時の
writelnなどの仕様に依存しない。 - 確実に「コンパイル時に決まる定数」だけになる。
- 通常のサンプルコードとの差別化が出来る。
- 組み込みならでは表示がうれしい。
- 実行時の
-
- 2進数( Binary )
-
プログラミング相手(CPU)の思考は2進数です。
- 整数リテラル( Integer Literals )
-
リテラルで 10進数 以外の表記が出来ます。
/* ! -c 指定でコンパイル */ pragma( msg, "10 = ", 10, /* * 2進数 * 0b か 0B で始まり 0 か 1 */ "\n0b10 = ", 0b10, /* * 16進数 * 0x か 0X で始まり * 0..9 と a..f、A..F */ "\n0x10 = ", 0x10, // "\n\n1_0_0 = ", 1_0_0, "\n0b1_0_0 = ", 0b1_0_0, "\n0B_1_0_0 = ", 0B_1_0_0, "\n01_0_0 = ", 01_0_0, "\n0_1_0_0 = ", 0_1_0_0, "\n0x1_0_0 = ", 0x1_0_0, "\n0X_1_0_0 = ", 0X_1_0_0, // 16進数は 0-9 と a-f、 A-F "\n\n0xabcdef = ", 0xabcdef, "\n0xABCDEF = ", 0xABCDEF, "\n0XaB_cD_eF = ", 0XaB_cD_eF );
-c指定でコンパイルD:\Pen-Jr\My Programs\types>dmd test -c 10 = 10 0b10 = 2 010 = 8 0x10 = 16 1_0_0 = 100 0b1_0_0 = 4 0B_1_0_0 = 4 0x1_0_0 = 256 0X_1_0_0 = 256 0xabcdef = 11259375 0xABCDEF = 11259375 0XaB_cD_eF = 11259375
※pragmaでも数値は10進数表示。ビット処理にも 2進数表記 はほとんど使われず 16進数表記 されます。
0で始まる 8進数表記 というのもありましたが、v2.054からなくなりました。 - こんぴゅーたー の基本は 永遠 に 2進数(たぶん)
-
512 やら 1024 のメモリーだとか、4096色表示だとか、半端な数字が多いのは、
import std.stdio, std.conv; // 10進数 = 2進数 void toBinary( in int n ){ writeln( n, " = ", // 値 n を2進数表記(文字列)に変換 to!string( n, 2 ) ); } void main(){ toBinary( 32 ); toBinary( 64 ); toBinary( 512 ); toBinary( 1024 ); toBinary( 4096 ); }
これは普通にコンパイルして実行
D:\Pen-Jr\My Programs\types>dmd test D:\Pen-Jr\My Programs\types>test 32 = 100000 64 = 1000000 512 = 1000000000 1024 = 10000000000 4096 = 1000000000000
最近の大容量 HDD が 3TB とかなのは細かいこと言わなくなったからで、モニターの解像度や Full HD だとかが 2進数 でも半端なのは別の理由からです。
- 16進数表記
-
基本は 2進数 ですが、常に 2進数 を意識する必要はありませんから、2進数表記
も必要なさそうですが、
例えば 整数値 は 8, 16, 32 ビットなどで、
import std.stdio, std.windows.charset, std.conv; /*---------------------------- * UTF8 から Shift-JIS へ変換 */ string toMBS( in string s ){ return to!string( toMBSz( s ) ); } /*---------------------------- * 2,16,10 進数で表示する */ void toMsg( in int wd, in uint last ){ writeln( wd, toMBS( "bit の 0 ~ 0b" ), to!string( last, 2 ), // 2進数表記で toMBS( " おば\n16進数でば 0 ~ 0x" ), to!string( last, 16 ), // 16進数表記で toMBS( "、 10進数でば 0 ~ " ), last, toMBS( " だ。" ) ); } void main(){ // bit数を数えやすいよう、2進数リテラルで関数を呼ぶ toMsg( 8, 0b1111_1111 ); writeln(); toMsg( 16, 0b1111_1111_1111_1111 ); writeln(); toMsg( 32, 0b1111_1111_1111_1111_1111_1111_1111_1111 ); }
D:\Pen-Jr\My Programs\types>dmd test D:\Pen-Jr\My Programs\types>test 8bit の 0 ~ 0b11111111 おば 16進数でば 0 ~ 0xFF、 10進数でば 0 ~ 255 だ。 16bit の 0 ~ 0b1111111111111111 おば 16進数でば 0 ~ 0xFFFF、 10進数でば 0 ~ 65535 だ。 32bit の 0 ~ 0b11111111111111111111111111111111 おば 16進数でば 0 ~ 0xFFFFFFFF、 10進数でば 0 ~ 4294967295 だ。
2進数表記 も大変です。
それぞれの 最大値 を明確に示すのは 2進数表記ですから、最もわかりやすい場合もあるでしょうが、あまりにも冗長で書くにも読むにも面倒です。
また、こういう場合の 10進数表記 はその意味が明確ではありませんし、それぞれに対応する値を憶える必要がありますが、16進数表記 を使えば明確になります。
また、10進数 への暗算には特殊能力が必要ですが、
import std.stdio, std.conv; // 16進数 = 2進数 void toBinary( in int n ){ writeln( "0x", to!string( n, 16 ), " = ", to!string( n, 2 ) ); } void main(){ toBinary( 32 ); toBinary( 64 ); toBinary( 512 ); toBinary( 1024 ); toBinary( 4096 ); writeln(); toBinary( 32 - 1 ); toBinary( 64 - 1 ); toBinary( 512 - 1 ); toBinary( 1024 - 1 ); toBinary( 4096 - 1 ); }
D:\Pen-Jr\My Programs\types>test 0x20 = 100000 0x40 = 1000000 0x200 = 1000000000 0x400 = 10000000000 0x1000 = 1000000000000 0x1F = 11111 0x3F = 111111 0x1FF = 111111111 0x3FF = 1111111111 0xFFF = 111111111111
16進数 への変換なら簡単・・・
もちろん一般的ではありませんから、初めは簡単ではないでしょうが、2進数処理 は 16進数表記 するのが 基本 です。
ほとんどの場合、標準は 10進数表示 ですし、高級言語では 2進数処理 が基本というわけではありませんから、10進数 でのプログラムは問題ありません。要は「10進数だけで十分」だと、16進数表記 を毛嫌いしないことです。
時に、2進数思考 と 10進数思考 の橋渡しもプログラマーの仕事になりますから。
- コードの無効化
-
書いてはみたけど、思惑通りに動かない・・・だとか、一時的に「プログラムコードの一部を無効にしたい」ということは良く起こります。
- コメントアウト
-
-
/+ +/ -
/+ import std.stdio, std.windows.charset, std.conv; /*---------------------------- * UTF8 から Shift-JIS へ変換 */ string toMBS( in string s ){ return to!string( toMBSz( s ) ); } /*---------------------------- * 2,16,10 進数で表示する */ void toMsg( in int wd, in uint last ){ /+ writeln( wd, toMBS( "bit の 0 ~ 0b" ), to!string( last, 2 ), // 2進数表記で toMBS( " おば\n16進数でば 0 ~ 0x" ), to!string( last, 16 ), // 16進数表記で toMBS( "、 10進数でば 0 ~ " ), last, toMBS( " だ。" ) ); +/ } +/ void main(){ /+ // bit数を数えやすいよう、2進数リテラルで関数を呼ぶ toMsg( 8, 0b1111_1111 ); writeln(); toMsg( 16, 0b1111_1111_1111_1111 ); writeln(); toMsg( 32, 0b1111_1111_1111_1111_1111_1111_1111_1111 ); +/ }
- version
-
