2010-03-30 (火)

C でクロージャ [C]

gcc 拡張を使うと、関数の中に関数を定義することができる。これを利用する
と C でもクロージャが使えることを少し前に知ったが、


ようやく理解できた...気がする。

クロージャとは


C 言語のコールバック関数に近いが、引数以外の変数を自身が定義された静的
スコープで解決することが最大の特徴。

...だと理解しています。^^;

コーディング例


#include <stdio.h>

/* 任意の関数 func を n 回実行するだけのライブラリ関数 */
void
dolist(void (*func)(void), int n)
{
    int i;

    for(i = 0; i < n; i++) {
	func();
    }

    return;
}

int
main(void)
{
    int level = 0;

    void lambda(void)
    {
	level++;
    }

    printf("%d\n", level);

    dolist(lambda, 1);
    printf("%d\n", level);

    dolist(lambda, 2);
    printf("%d\n", level);

    dolist(lambda, 3);
    printf("%d\n", level);

    return 0;
}



結果


0
1
3
6


Solaris9 の /usr/local/bin/gcc で確認した。

dolist は渡された処理(lambda)を、指定された回数分実行するだけのライブラ
リ関数。

ユーザ(main)は処理内容を、自分の静的スコープの中で自由に定義することが
できる。level を外部変数にしなくて良い点が素晴らしい。狭いスコープ大事。

lambda() を nm で確認したところ、t マークが付いていた。lambda() はスタッ
クに展開されているわけではなく、static な関数として定義されているという
こと。

lambda() と level の関係はどうなっているんだろう?

この記事に言及しているこのブログ内の記事

2009-11-21 (土)

UNIX 時間 [Emacs][UNIX][C]

業務で C 言語と、シェルコマンド date での UNIX 時間(1970 年 1 月 1
日 0:00 からの秒数)の取得方法を調べたのだけれど、我らが Emacs Lisp
を調べていませんでした。

Emacs Lisp


(time-to-seconds (current-time))


で良いようです。

真夜中ごろ - ポロポロ

業務で調べた UNIX 時間は以下。

シェルコマンド


% date +%s

=> 1257925989

※ Solaris9 の場合、SUN 謹製の date (/usr/bin/date) ではなく、
GNU の date (/usr/local/bin/date) を使う必要がある。

C言語


#include <stdio.h>
#include <sys/time.h>           /* gettimeofday() */

int
main(void)
{
    struct timeval tv;
    double unix_time;

    gettimeofday(&tv, NULL);

    unix_time = tv.tv_sec + (tv.tv_usec * 0.000001);

    printf("%f\n", unix_time);

    return 0;
}


=> 1257926292.479697

この記事に言及しているこのブログ内の記事

2009-07-02 (木)

セキュアコーディング [C]

セキュアコーディング - JPCERT コーディネーションセンター

ここに無料セミナーの案内が掲示されています。

C/C++ セキュアコーディング ハーフデイキャンプのご案内
- Part 1. 7月16日(木) 13:00-18:00 「文字列、整数」
- Part 2. 8月 7日(金) 13:00-18:00 「ファイル入出力」
- Part 3. 9月10日(木) 13:00-18:00 「動的メモリ管理、書式指定文字列」


昨年度の資料をダウンロードできます。
http://www.jpcert.or.jp/research/materials.html

セキュアコーディングのドキュメントもダウンロードできます。
http://www.jpcert.or.jp/sc-rules/

まだ読んでないけど、無料とはすごい!!

2009-05-24 (日)

main() の第 3 引数 [C]

処理系に依存してしまうが、main() の第 3 引数には環境変数リストが入っ
ているとのこと。うちの Debian GNU/Linux squeeze では参照できた。

#include <stdio.h>
int main(int argc, char **argv, char **envp){
    int i;
    for (i = 0; envp[i] != NULL; i++){
        printf("%s\n", envp[i]);
    }
    return 0;
}



(URL: 404 Blog Not Found:CGIの神話と現実)
(URL: int void (main)の意味/// -OKWave)

2009-04-07 (火)

gcc の -Wextra オプション [C]

[2009-04-07-2] を調べていく過程で -Wextra オプションを知った。gcc3
までは -W とのこと。-Wall って、"all" じゃないのか。。。

-Wextra は、-Wall よりも厳しめの警告を出すようだ。両方有効にしたい
場合は、"-Wall -Wextra" と指定する。

詳しくは gcc の info に書いてあるみたい。確認してみるか。

(URL: http://at-aka.blogspot.com/2006/11/gcc-wall-w.html)
(URL: http://sugarpot.sakura.ne.jp/yuno/?gcc%2Fwarning)

2009-03-20 (金)

printf() のような関数を自作した。 [C]

せっかくの休みなのでw、printf() のような関数を自作してみた。

static char my_buffer[1024 * 1024];

extern void my_printf(const char *fmt,...);


訳あって、書き出し先は my_buffer という外部変数。
va_list も訳あって使えないので、可変長引数は自前で読み込む。

可変長引数はどう読み込めば良いか? C 言語の場合、内部変数はスタック
に積まれるため、後に宣言したものの方が若いアドレスになる。でも、引
数の場合は違っていて、「引数1」の次のアドレスに「引数2」が存在する
ことが保証されているらしい。
(URL: http://networkprogramming.blog18.fc2.com/blog-entry-7.html)

これを利用すれば、可変長引数を自前で読み込むのは簡単。
fmt の中に %d や %x が見つかるたびに param32p を読み進めていけば良い。

void
my_printf(const char *fmt,...)
{
    unsigned long int *param32p = (unsigned long int *)&fmt + 1;



ところが!!試しに最適化レベルを 3 にしたら、「引数1」の *前の* ア
ドレスに「引数2」が存在していた。ガセだったか...。以下のページにも
可変長引数を扱う時は stdarg.h 使えと書いてあった。va_list が使えな
いというのは勘違いな気がしてきたので、後で確認してみよう。
(URL: http://docs.hp.com/ja/B2355-90858/stdarg.5.html)

itoa() も使えないため自作した。「符号あり/なし 10 進数」と「符号な
し 16 進数」をサポートしたが、意外に大変だった。一番時間かかったかも。

やっと printf() モドキが完成!!
と言いたいところだけど、"%d" の数と可変長引数の数が合ってなくても
warning にならないのね。ちょっとヤダなあ...。

調べてみたら、gcc 系の場合以下のように宣言すれば良いことが分かった。

extern void my_printf(const char *fmt,...)
#ifdef __GNUC__
    __attribute__ ((format (printf, 1, 2)))
#endif  /* __GNUC__ */
    ;



__attribute__ については、以下にある程度まとまっていた。
いろいろあるなあ。。。
(URL: http://sugarpot.sakura.ne.jp/yuno/?gcc%2Fattribute)

追記(2009-03-21):
コメントにもありますが、最適化レベル 3 で動作が変わったのはインライ
ン展開されていたためでした。インライン化できないような単純でない関
数にしたり、__attribute__((noinline)) を付けたりすれば大丈夫そうで
すが、移植性が落ちるのでやはり避けた方が良いと思います。

2009-03-14 (土)

同一ネットワーク上のマシン同士でのプロセス間通信 [UNIX][C]

以下の Web site にサンプルソースとともに簡潔にまとめられていた。
素晴らしい。
(URL: http://www.ueda.info.waseda.ac.jp/~toyama/network/example2.html)

以下のマシンでテストした。


サーバ -> Cygwin on WindowsXP
クライアント -> Debian GNU Linux squeeze (testing)

make 時の注意


- Debian では libsocket が見つからなくてリンクエラーになった。
Linux では不要らしいので、Makefile 中の -lsocket を削除した。
- Cygwin では libsocket と libnsl が見つからなくてリンクエラーに
なった。両方とも cygwin1.dll に含まれているらしいので、Makefile 中
の -lsocket と -lnsl を削除した。

テスト


- Cygwin で iserver.exe を実行し、クライアントからの通信待ち受け状
態にした。
- Linux で iclient を実行した。そのまま文字列を打ち込んだら、大文字
に変換されて表示された。成功!

補足


- 大文字への変換は iserver.c の toupper() で行っている。iclient は
標準入力から受け取った文字列をサーバに送り、送り返された文字列を
printf() しているだけ。

2006-12-19 (火)

const の位置 [C]

(1) const int *p;
(2) int *const p;
(3) int const *p;

(1) は const int なので、*p が read only になる。
(2) は *const なので、p が read only になる。
(3) は (1) と同じ。

2006-05-25 (木)

データ型のサイズ [C]

char=1byte固定
(整数型)
short int <= int <= long int
short int は short と記述可能
long int は long と記述可能
(実数型)
float <= double <= long double

(URL: http://www9.plala.or.jp/sgwr-t/c/sec13.html)

2004-12-10 (金)

C言語で、小数の小数部分だけを抜き出す方法 [C]

その1

float shousuu, zenbu = 1.5;
shousuu = zenbu - (int)zenbu;



その2

#include <math.h>
float zenbu = 1.5, seisuu, shousuu;
shousuu = modff(zenbu, &seisuu);


2004-09-29 (水)

関数の引数に文字列があると、BSS 領域に取られるようだ [C]

printf() を削除したときに BSS のサイズが減っていて気づいた。

2003-03-01 (土)

enumの最後の `,' [C]

[mew-dist 18862]
enumの最後の `,' は K&R では "ない" のが正解。
しかし、C99d に対応したコンパイラ(例: GCC 2.96以降)では OK。
関連URL => プログラミング言語 C の新機能 <http://seclan.dll.jp/c99d/c99d00.htm>

2003-01-07 (火)

トライグラフ [C]

warning: 6 trigraph(s) encountered

??で始まる文字列はプリプロセッサによって置換される可能性がある。K&R P287参照。

2002-10-01 (火)

外部変数のアドレスが決まるタイミング [C]

static な外部変数はコンパイル時、
extern な外部変数はリンク時にアドレスが決定される。

2002-09-03 (火)

型変換 [C]

from himi

C言語では、
P +- P -> I
P +- I -> P
が、型変換として保証されているので、pointerはpointerのまま、増減の分だけ
integerとして計算すればよろしい。(Pはpointer, Iは整数型)

2002-08-19 (月)

プリプロセスのみ [C]

gcc でプリプロセッサだけを走らせてコンパイルはしたくないときは
'-E' オプションを付ければよい。

2002-07-15 (月)

セクション構造 [C]

.text
実行コードを格納するセクション
実行・読み込みのみ可能で書込みは不可
.rodata
定数値を格納するセクション
読み込みのみ可。書込み・実行は不可
.data
初期化済みデータを格納するセクション
読み書きのみ可。実行は不可
.bss
非初期化データを格納するセクション
読み書きのみ可。実行は不可
bss はプログラムがロードされた時点で 0 クリア
されるべき領域だそうです。
bss が外部変数領域とすると、data はカラー関係の
テーブルのようなものでしょうかね ??

2002-04-09 (火)

Solaris9 での double と long long のサイズ [C][Solaris9]

sizeof(double) == 8
sizeof(long long) == 8

2002-04-01 (月)

gcc の最適化オプション [C]

gccに、オプション'-O2'を付けると、コードを最適化できる。
知っていたけど、gdbの変な動きと結び付かなかった。。。

最終更新時間: 2017-06-29 08:15

検索
最近の話題
- 2017-06-29
  Kubernetes Meetup Tokyo #5 に行ってきた #k8sjp
- 2017-06-26
  『プログラマのためのGoogle Cloud Platform入門』を読んだ
- 2017-06-02
  AWS Summit Tokyo 2017 に行ってきた #AWSSummit
- 2017-05-28
  GitHub Organization をメンテナンスするスクリプトを作った
- 2017-04-29
  Docker ではないコンテナ systemd-nspawn を使ってみた
- 2017-04-16
  CircleCI 2.0 で capistrano デプロイしてみた
- 2017-04-15
  CircleCI 2.0 をローカルで実行できる circleci コマンドとは何者か
最近追記された記事
- 2017-04-29-1 (60日前)
- 2017-04-13-1 (74日前)
- 2017-04-13-1 (76日前)
- 2017-03-02-1 (118日前)
- 2017-02-25-1 (123日前)
- 2017-02-21-1 (127日前)
- 2015-06-07-1 (133日前)
- 2016-10-19-1 (142日前)
- 2016-01-01-1 (154日前)
- 2015-01-04-1 (163日前)
カテゴリ
- Anthy (3)
- Apache (11)
- Apple (1)
- ATOK (4)
- au (3)
- AWS (18)
- Bazaar (1)
- Berkshelf (2)
- BigQuery (1)
- BitBar (3)
- Book (86)
- Boxen (2)
- Bugsnag (1)
- C (26)
- capistrano (4)
- chalow (56)
- ChatWork (1)
- Chef (17)
- Chrome (3)
- Chromecast (1)
- CircleCI (10)
- Comics (2)
- Cooking (10)
- cvs (15)
- cygwin (12)
- D3.js (1)
- Debian (55)
- Docker (3)
- E-mail (8)
- elasticsearch (4)
- Emacs (219)
- Emacs講座 (10)
- English (4)
- feedforce (7)
- fetchmail (3)
- Firefox (20)
- Fluentd (4)
- ftp (1)
- Game (20)
- GCP (1)
- Gem (5)
- Git (9)
- GitHub (16)
- Go (5)
- Google (1)
- gpg (4)
- GrowthForecast (7)
- Health (3)
- Heroku (9)
- Homebrew (10)
- HTML (6)
- iBook (1)
- iPhone (15)
- IRC (1)
- Jenkins (8)
- JS (1)
- Karabiner (1)
- KeySnail (3)
- Kibana (1)
- Kindle (1)
- Kubernetes (1)
- Langrich (7)
- LDAP (6)
- Life (19)
- Linux (6)
- Mackerel (1)
- Mew (18)
- MongoDB (1)
- Mozilla (19)
- Music (1)
- MySQL (1)
- NAS (4)
- nginx (6)
- NHK (1)
- Node (1)
- ntp (4)
- OOP (1)
- OpenID (2)
- openssl (1)
- Opera (2)
- OSX (41)
- Perl (14)
- PHP (19)
- PostgreSQL (1)
- procmail (4)
- Programing (3)
- Puppet (1)
- Python (2)
- Rails (12)
- Rake (2)
- RaspberryPi (1)
- RedHat (29)
- Redmine (3)
- Rspec (1)
- Ruby (49)
- samba (3)
- screen (7)
- sed (5)
- serverspec (6)
- sh (8)
- Slack (2)
- Solaris9 (22)
- Spring (2)
- ssh (4)
- StatusNet (21)
- svn (12)
- Swift (1)
- Tablet (1)
- tdiary (3)
- Twitter (14)
- Twmode (6)
- Ubuntu (5)
- UNIX (102)
- vagrant (8)
- Video (21)
- vim (1)
- Wercker (9)
- Windows (29)
- Wine (3)
- XML (11)
- XP (1)
- zsh (25)
- インストールメモ (33)
- クイックシェイプ (12)
- ネタ (15)
- 勉強会 (15)
- 携帯 (6)
- 正規表現 (4)
過去ログ
2017 : 01 02 03 04 05 06 07 08 09 10 11 12
2016 : 01 02 03 04 05 06 07 08 09 10 11 12
2015 : 01 02 03 04 05 06 07 08 09 10 11 12
2014 : 01 02 03 04 05 06 07 08 09 10 11 12
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12
2002 : 01 02 03 04 05 06 07 08 09 10 11 12
2001 : 01 02 03 04 05 06 07 08 09 10 11 12
Google+