« 2007年12月 | トップページ | 2008年2月 »

2008年1月の4件の記事

2008年1月 9日 (水)

strncpyとfgets

今更ですが、Cの文字列を扱う標準関数についてメモ。

strncpy(char *dst, const char *src, size_t n)
とは、
  • srcの指すアドレスからnバイト分の領域Aを、dstの指すアドレスから始まる領域Bにコピーする
  • ただし、Aの途中で'\0'があった場合はそれ以降のBは'\0'で埋める
  • コピー元Aとコピー先Bの領域がダブった場合の挙動は未定義

です。これが何を意味するかというと、

  • srcの指すアドレスからnバイト以内(領域A)に'\0'が無いと、strncpyは領域Bに'\0'を書き込まない
  • dstの指すアドレスからnバイト(領域B)には必ず何かが書き込まれる

すなわち、srcの指すアドレスから始まる「文字列」の長さが不明の場合に、strncpy()を安全に使おうと思ったら、

  • dstの指すアドレスから始まる領域には、n+1バイト(以上)を確保しておく
  • dst[n]には'\0'を入れておく

必要があります。まず、少なくとも領域Bにはnバイトを確保していないと領域破壊が起こりますし、n+1番目すなわちdst[n]に'\0'を入れておかないと、領域Bの'\0'終端が保証されません。ですので結局、領域Bには末尾の'\0'を含めてn+1バイトが必要になります。

 注目すべきはfgets( char *string, int n, FILE *stream)との哲学の違いです。上記のとおり、strncpy()は、nバイトコピーすることに一生懸命で、'\0'終端することにはあまり興味がありません(途中で'\0'に出会うと、それ以降'\0'でコピーしますが、これもよく考えると謎な仕様ですね)。一方fgetsは「Cでは文字列は'\0'で終端されていなければならないので、fgetsが書き込む領域はfgets自身が必ず'\0'で終端」します。fgetsは、streamから1行分、すなわち'\nまで読み込んでstringから始まる領域に書き込もうとしますが、上限のサイズnが与えられています。この上限値を使うやり方としては、

  1. 最大n文字を書き込んで、n+1文字目に'\0'を書く(=stringにはn+1バイトの確保が必要)
  2. 最大n-1文字を書き込んで、n文字目に'\0'を書く(=n-1文字しか取得されない)

の2通りがあるかと思います。一長一短がありますが、実際のfgetsは、おそらく領域破壊の可能性が低いと考えたのでしょう、「2.」の仕様になっています。

サンプルはこんな感じ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>

#define STR_LENGTH 1023
#define BUFFER_LENGTH 1023

void get_str(char*, int);

int main(void)
{
    char str_array[STR_LENGTH + 1];
    memset(str_array, '\0', sizeof(str_array));
    get_str(str_array, sizeof(str_array) - 1); //領域のサイズ-1がミソ
    printf("%s\n", str_array);
    exit(0);
}

/* p_strで指すアドレスからsize_of_strバイトの領域に書き込む */
void get_str(char *p_str, int size_of_str)
{
    char buff[ BUFFER_LENGTH + 1 ];
    memset(buff, '\0', sizeof(buff)); // この初期化は厳密には不要

    FILE *fp = NULL;
    fp = fopen("hoge.txt", "r");
    fgets(buff, sizeof(buff), fp); // fgetsはsizeof(buff)でOK

    strncpy(p_str, buff, size_of_str); // buffのサイズではない!
}

 うーん、配列宣言でよくあるarray[ LENGTH + 1 ]の「+ 1」の意義ってあまり上手く説明できないなぁ。仕様上の最大文字数+'\0'の1バイトって意味なんだろうけど。。はじめっから「仕様上の最大文字数 + 1」を#defineしとけばいいじゃんって気もするし。単なる慣習ってことかしら。

では、また。

[追記] ソース、やっぱりバグってたので、コンパイルが通る程度に修正しました。

| | コメント (0) | トラックバック (0)

2008年1月 8日 (火)

今年の目標

去年は色々がんばったけど、目標はほとんど未達成でした。今年2008年の目標を立ててみます。

  • LPIC LV1取得
  • LPIC LV2取得
  • テクニカルエンジニア(情報セキュリティ)取得
  • TOEIC 3回受験
  • TOEIC 800
  • 簿記1級取得
  • 「CPUの創り方」で、CPUを作成する
  • それに加えて、Write Great Code でCPUのアーキテクチャを理解する
  • 100冊読む
  • 公開サーバを立ち上げる
  • Ruby on Rails + MySQLでアプリを作成する
  • OSSに寄与する
  • 4半期ごとに目標を見直す★去年の反省を生かしての改善点

3年前はマネーゲームな年でした。2年前は死んでいました。去年はリハビリと自己啓発の年でした。今年は今後の10年を見据えての年(0年目)にしたいと思います。

というわけで、10年後2018年1月8日までの目標です。10カ年計画の第一歩です。

  • 年収3,000万円
  • OSSのメンテナーとなる
  • 本を出版する

大きく出てますか?大きく出てますね。では、また。

| | コメント (1) | トラックバック (0)

2008年1月 6日 (日)

暗黒宇宙で銀河が生まれる

久しぶりの宇宙本。本書のキモは二つ

  • ダークマターの実証の報告
  • 数式による説得力のある解説

です。

ダークマターって、単に光っていないだけの岩の固まりかと思っていたら、そもそも地球上に存在する元素とは違うものなんですね。で、その正体についてはまだ確かなことは分っていないとか。そのダークマターの立体的な分布図を描き、それが銀河の分布と重なっている(=銀河の誕生にダークマターが関係している)ことを立証したっていう2007年初頭の発見の報告が、本書の本筋です。

加えて、宇宙論の基本的な考え方について中高生レベルの簡単な数式を交えて定量的に説明しているというのが、本書のもうひとつの売りだと思います。こういう本を読むと、数学って言うのが自然科学を記述するための言語なんだなぁということが実感できます。数学使わないと正しく表現できないんですよね。

#とはいえ、僕は大学の数学がさっぱり分らなかったクチなのですが。。。

フルカラーで、最新の写真が載ってて、1000円とはずいぶん安いと思います。深宇宙の写真や、重力レンズ効果で曲がってみえる写真なんて初めて見ました。しかも、重力レンズ効果で、さらに遠くの星も見えるようになるんですね。。。とまぁ、色々な知識も増えました。

あえて欠点を挙げるとすれば、図がたくさん載っているがゆえに、図への参照がたくさんあってページをめくる必要が多いことくらい。あと、これは個人的な素養の問題かもしれませんが、数字がたくさん出てくるのですが、「相場観」がないので覚え切れません。天の川銀河の直径がどのくらいとか、何光年先にある銀河が生まれてから何億年の銀河だとか。。。ちゃんと勉強しつつ読まないと正しく理解できませんね。

最新の宇宙論、深宇宙、ダークマターに興味のある方、おススメです。

| | コメント (0) | トラックバック (0)

2008年1月 3日 (木)

富の未来(上)

アルビン・トフラーです。先輩に借りました。昔パワーシフトが出版されたとき(まだ子供でした)は、「未来学者」なんて怪しいやつだなぁと思っていたのですが。

変化が早いと言われている今、何が正しいのか?何が起こっているのか?これからどうなるのか?について、(おそらく)豊富な調査に基づいて述べている本です。昨年中に読み終わるはずが、やっと三が日で読み終わりました。

#あと、下巻と、ウィキノミクスと、増補改訂版が出たらしいフラット化する世界が残っています。

続きを読む "富の未来(上)"

| | コメント (0) | トラックバック (0)

« 2007年12月 | トップページ | 2008年2月 »