最低限あると嬉しいvimrc
大抵もっとごちゃごちゃ書いてあるけど、個人的に最低限あると嬉しいvimrcの設定だけをピックアップ。
$cat ~/.vimrc syntax on "色設定 colorscheme desert "前回編集終了位置からの再開 augroup vimrcExtend au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" augroup END "C/C++ファイルのみ拡張Tab設定 autocmd FileType c,cpp set expandtab "インデント関連 set cindent set cinoptions=:0,p0,t0 set cinwords=if,else,while,for,do,switch,case set backspace=2 set tabstop=4 set shiftwidth=4 "文字コード set encoding=utf-8 set fileencodings=utf-8,iso-2022-jp,cp932,sjis,euc-jp "行表示 set nu "検索時のハイライト set hlsearch "ショートカット nmap <ESC><ESC> : nohlsearch <CR> nmap <TAB> : set nu <CR> nmap <TAB><TAB> : set nonu <CR>
ソースコードと完全に同じ文字列を出力する
実用性はゼロですが、お遊び感覚でCとperlでやってみた。
Perlの場合
quine.pl
$_=q{ q[ * * * * * * * * * * * * * * Hello Quine * * * * * * * * * * ]; print"\$_=q{$_};eval\n"};eval
実行結果
$ perl quine.pl $_=q{ q[ * * * * * * * * * * * * * * Hello Quine * * * * * * * * * * ]; print"\$_=q{$_};eval\n"};eval
Cの場合
quine.c
#define quine(x) main(){return puts(#x"\nquine("#x")");} quine(#define quine(x) main(){return puts(#x"\nquine("#x")");})
実行結果
$ gcc -o quine quine.c $ ./quine #define quine(x) main(){return puts(#x"\nquine("#x")");} quine(#define quine(x) main(){return puts(#x"\nquine("#x")");})
C言語で簡易関数トレース
シンプルなprintf()デバッグをコンパイルスイッチでON/OFFできるように実装する。
trace.c
#include <stdio.h> #ifdef DEBUG_ENABLE #define ENTRANCE(fmt, ...) \ printf("%s:%u:===> IN %s(" fmt ")\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__); #else #define ENTRANCE(fmt, ...) #endif /* DEBUG_ENABLE */ #ifdef DEBUG_ENABLE #define EXIT(fmt, ...) \ printf("%s:%u:<=== OUT %s(" fmt ")\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__); #else #define EXIT(fmt, ...) #endif /* DEBUG_ENABLE */ #ifdef DEBUG_ENABLE #define LOG_DEBUG(fmt, ...) \ printf("%s:%u:%s(): " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__); #else #define LOG_DEBUG(fmt, ...) #endif /* DEBUG_ENABLE */ int function(int a) { int ret = 0; ENTRANCE("a=%d", a); EXIT("ret=%d", ret); return ret; } int main(void) { ENTRANCE(); LOG_DEBUG("hello world"); int a = 1; int b = 2; LOG_DEBUG("a + b = %d", a+b); function(a); EXIT(); return 0; }
実行例
$ gcc -DDEBUG_ENABLE trace.c $ $ ./a.out trace.c:35:===> IN main() trace.c:37:main(): hello world trace.c:41:main(): a + b = 3 trace.c:27:===> IN function(a=1) trace.c:29:<=== OUT function(ret=0) trace.c:45:<=== OUT main() $
あくまで簡易的なのでソースコードの規模が大きくなるほど見にくくなる予感。
trace.c:35:===> IN main() trace.c:27: ===> IN function(a=1) trace.c:29: <=== OUT function(ret=0) trace.c:45:<=== OUT main()
こんな感じで、関数のIN/OUTでスタックが深くなるにしたがって表示が右にシフトしていくような機能が欲しい。
後は、タイムスタンプとsyslogのようにログレベルを指定してログの出力量を調整できる機能を追加したい。
コードの処理速度計測にgprofを試してみた
GNUのプロファイラ gprofでコードの処理速度計測を試してみた。
関数単位、LINE(行)単位での実行速度の計測ができる模様。
今回は関数単位でお試し。
使い方は"-pg"のオプションを付与してコンパイルしたバイナリを実行後にgprofコマンドをかませばOK。
gproftest.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define LOOP_BASE_COUNT (100*1000) void function1(void) { char buf1[1024] = {0}; char buf2[1024] = {0}; /* メモリ操作で負荷をかける */ for(int i = 0; i < LOOP_BASE_COUNT; i++) { memset(buf1, 0xff, sizeof(buf1)); memcpy(buf2, buf1, sizeof(buf2)); } } void function2(void) { char buf1[1024] = {0}; char buf2[1024] = {0}; for(int i = 0; i < LOOP_BASE_COUNT*10; i++) { memset(buf1, 0xff, sizeof(buf1)); memcpy(buf2, buf1, sizeof(buf2)); } } void function3(void) { char buf1[1024] = {0}; char buf2[1024] = {0}; for(int i = 0; i < LOOP_BASE_COUNT*1000; i++) { memset(buf1, 0xff, sizeof(buf1)); memcpy(buf2, buf1, sizeof(buf2)); } } int main(void) { function1(); function2(); function3(); return 0; }
$ cat Makefile gproftest: gproftest.c gcc -O2 -pg -std=gnu99 -o gproftest gproftest.c
実行例
$ make gcc -O2 -pg -std=gnu99 -o gproftest gproftest.c $ $ time ./gproftest real 0m10.355s user 0m10.341s sys 0m0.004s $ $ $ gprof gproftest gmon.out Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls s/call s/call name 99.88 10.31 10.31 1 10.31 10.31 function3 0.98 10.41 0.10 1 0.10 0.10 function2 0.00 10.41 0.00 1 0.00 0.00 function1 ...(後略)...
[その他]
どうやらコンパイル時に -O3 で最適化すると上手くいかないぽい。
linuxでkbhit()
kbhit.h
#ifndef _KBHIT_H_ #define _KBHIT_H_ #include <stdbool.h> #include <termios.h> #include <unistd.h> extern void KB_open(void); extern void KB_close(void); extern bool kbhit(void); extern char linux_getch(void); #endif /* _KBHIT_H_ */
kbhit.c
#include "kbhit.h" static struct termios Old_set; static struct termios New_set; static int ReadChar = -1; void KB_open() { tcgetattr(0,&Old_set); New_set = Old_set; New_set.c_lflag &= ~ICANON; New_set.c_lflag &= ~ECHO; New_set.c_lflag &= ~ISIG; New_set.c_cc[VMIN] = 0; New_set.c_cc[VTIME] = 0; tcsetattr(0,TCSANOW,&Old_set); } void KB_close() { tcsetattr(0,TCSANOW, &Old_set); } bool kbhit() { char ch; int nread; if(ReadChar !=-1) { return true; } New_set.c_cc[VMIN]=0; tcsetattr(0,TCSANOW,&New_set); nread=read(0,&ch,1); New_set.c_cc[VMIN]=1; tcsetattr(0,TCSANOW,&New_set); if(nread == 1) { ReadChar = ch; return true; } return false; } char linux_getch() { char ch; if(ReadChar != -1) { ch = ReadChar; ReadChar = -1; return (ch); } read(0,&ch,1); return(ch); }
main.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { KB_open(); while(1) { if (kbhit()) { char ch = linux_getch(); printf("kbhit: %c\n", ch); if ('q' == ch) { break; } } usleep(10000); } KB_close(); }
kbloop: kbhit.o main.o gcc -o kbloop kbhit.o main.o kbhit.o: kbhit.h kbhit.c gcc -c kbhit.c main.o: main.c gcc -c main.c clean: rm -f *.o
実行例
$ make gcc -c kbhit.c gcc -c main.c gcc -o kbloop kbhit.o main.o $ $ ./kbloop kbhit: a kbhit: b kbhit: c kbhit: d kbhit: e kbhit: f kbhit: g kbhit: q $ $
HTML,JavaScriptで格子を描画
canvas.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <!-- キャンバスの設定 --> <canvas id="canv" width="500" height="500"></canvas> <script> var ctx = document.getElementById("canv").getContext('2d'); // 描画内容を指定する // 背景を500×500の緑で描画 ctx.fillStyle = "rgb(0,128,0)"; ctx.fillRect(0, 0, 500, 500); // 格子の設定 ctx.strokeStyle = "white" ctx.lineWidth = 2; ctx.beginPath(); // 縦線 for (var v = 50; v < 500; v+=50) { ctx.moveTo(v, 0); ctx.lineTo(v, 500); } // 横線 for (var h = 50; h < 500; h+=50) { ctx.moveTo(0, h); ctx.lineTo(500, h); } // 描画内容を実行する ctx.stroke(); </script> </body> </html>
実行例
C言語でbuffer overrun
お呼びでない関数を実行する。
overrun.c
#include <stdio.h> #include <stdlib.h> void goast(void) { printf("Boo!\n"); } void dummy(void) { char a[1] = {0}; a[9] = &goast; } int main(void) { dummy(); return 0; }
実行例
$ gcc overrun.c overrun.c: In function 'dummy': overrun.c:13: warning: assignment makes integer from pointer without a cast $ ./a.out Boo! Segmentation fault