(C++)メンバ関数のポインタでエラー
2005-12-08-2 / カテゴリ: [programming][c] / [permlink]

Visual C++にて
class Hoge {
:
  int foobar();
:
};
なメンバ関数に対し、クラス内の別メソッドで
*func = &this->foobar;
とすると
error C2276: '&' : 仮想関数のアドレスを取ろうとしました。
となってしまう。

このあたりによると、
staticメンバ関数か(C-likeな)グローバル関数でないと駄目です。
理由は、「関数のアドレスが決定できない」です。
なんだって。

オブジェクトが生成されるまでメンバ関数はメモリ上のどこにあるかわからない(というかない?)ってことかな。

とりあえずクラスの定義で
class Hoge {
:
  static int foobar();
:
とすれば OK になった。
実際の関数の定義は
int Hoge::foobar() {
:
:
}
で、static は要らない。(というか、つけるとエラーになる)

構造体のパディングをつめる
2005-12-08-1 / カテゴリ: [programming][c] / [permlink]

「pack プラグマ」を使う

[2005-12-04-1]の続き
struct fromdata {
  unsigned char first;
  unsigned char second;
  unsigned char third;
};

#pragma pack(push, 1)
struct todata {
  unsigned first: 6;
  unsigned second: 6;
  unsigned third: 6;
  unsigned forth: 6;
};
#pragma pack(pop)
(以下略)
これで結果が
from: 3
to: 3
になった。

#pragma pack(n)
これで、それ以降の構造体・共用体のパディングに適用される
#pragma pack(push, n)
#pragma pack(pop)
(push,n)で、以降の構造体・共用体のパディングを n を基準にし、(pop)で元にもどす

テストコード書いてみたが、エンディアン関係??でサクっとは base64 変換できねぇ...(@Intel pentium M)

構造体でビットフィールド
2005-12-04-1 / カテゴリ: [programming][c] / [permlink]

独習Cにも載ってたけど気づかなかった。
構造体のメンバにchar(1バイト)以下の単位で、ビット単位のメンバを持たせることができる。
struct foo {
  int a: 1;    // 1ビットの領域
  int b: 3;    // 3ビットの領域
  int c: 2;    // 2ビットの領域
};
true/false の2値しか必要ないとかに使える。

このビットフィールドと共用体を併用すれば、ビット演算使わずに base64 エンコード/デコードできるかなーと思ったけど、sizeof(struct foo) は 4. パディングはしっかり入ってるのね...

struct fromdata {
  unsigned char first;
  unsigned char second;
  unsigned char third;
};

struct todata {
  unsigned first: 6;
  unsigned second: 6;
  unsigned third: 6;
  unsigned forth: 6;
};

union base64 {
  struct fromdata from;
  struct todata to;
};

int main() {
  printf("from: %d\n", sizeof(struct fromdata));
  printf("to: %d\n", sizeof(struct todata));
  return 0;
}
結果は
from: 3
to: 4
うーん
Referrer (Inside): [2005-12-08-1]

VC6.0 で定義位置にジャンプした後、ジャンプ元に戻る
2005-12-03-1 / カテゴリ: [win][programming][c][VC++] / [permlink]

Ctrl-NUM*
Shift-: じゃなくてテンキーの '*' な
Referrer (Inside): [2005-12-14-1]

VC6.0 でブレークポイントの一括解除
2005-12-01-1 / カテゴリ: [win][programming][c][VC++] / [permlink]

Ctrl-Shift-F9
プロジェクト内の複数ファイルを一括、かな。

VC6.0 で対応する括弧へジャンプする
2005-11-30-1 / カテゴリ: [win][programming][c][VC++] / [permlink]

括弧にカーソルにあわせ、
Ctrl-E
もしくは
Ctrl-]
で。
Shift を同時に押下すればブロックが選択状態になるのでさらに見やすいかも。
Referrer (Inside): [2007-03-05-1]

dsw ファイルから起動した時、プロジェクト毎に Visual C++ を起動する(VC6.0)
2005-11-18-1 / カテゴリ: [win][programming][c][VC++] / [permlink]

標準状態だと、dsw ファイル(プロジェクト ワークスペース)をダブルクリックした時は、Visual C++ が起動してなければ新規に起動し、すでに起動していれば(で、他のプロジェクトを開いていればそれを閉じて)起動中の Visual C++ で開かれる。
で、個人的には複数のプロジェクトを開いていてほしーんだけど。

調べたらいくらでもヒットしたんで、簡単に。
フォルダオプションのファイルの種類で、dsw ファイルの詳細設定の[MSDEVで開く(O)]を編集し、[DDEを使う(U)]のチェックをはずす。
で dsw ファイルをダブルクリックすれば、ファイル(プロジェクト)毎に Visual C++ が起動する。

可変長引数
2005-11-04-2 / カテゴリ: [programming][c] / [permlink]

めも

各変数を自前で取り出して使う場合
#include <stdarg.h>
/* 引数を全部足して返す */
int sumall(int n, ...) {
  va_list ap;
  int total = n;
  int n_tmp = 0;

  va_start(ap, n);   /* 最後の固定変数を指定し,最初の可変長引数をセットする */
  while ((n_tmp = va_arg(ap, int)) != 0) {
    total += n_tmp;  /* 型を指定することで引数を一つ取り出す.
                        ap には次の引数がセット */
  }
  va_end(ap);        /* 後始末 */

  return total;
}
というわけで,va_xxx には「引数の最後」が何かを知る術はないようなので,固定引数部分に引数の個数を入れるか,番兵を使うかするっぽい.(上のコードは 0 があったら終了する)
また,型情報が必要なので,複数の型を扱うときは工夫が必要.

printf(3) 関係のラッパ
#include <stdarg.h>
void error(char *fmt, ...) {
  va_list ap;

  fprintf(stderr, "%s", "Error! ");
  va_start(ap, fmt);
  vfprintf(stderr, fmt, ap);
  va_end(ap);
  exit(1);
}
vprintf(3) や vfprintf(3) には,ap を渡せば期待する動作になるかと.

printfのフォーマットで桁数を変数指定
2005-11-04-1 / カテゴリ: [programming][perl][c] / [permlink]

 * を使う

printf("%*d", width, val);
で,width で桁数を指定できる.
width を負の数にすれば,左寄せも可.

Perl でもまったくおんなじ
printf("%0*d\n", $width, $val);
こっちはゼロ詰指定

static 変数 static 関数
2005-11-03-2 / カテゴリ: [programming][c] / [permlink]

2種類あるのが紛らわしいのでメモ

(1) 外部変数・関数の static
static 関数および,static な外部変数(グローバル変数)は,「スコープはファイル」になって,ほかのファイルからは参照できなくする.

(2) 内部変数の static
関数内の内部変数に static がつくと,スコープは変化なく,「寿命がプログラム終了まで」になり,関数(ブロック)終了後も生き残る.よくある例は再帰処理内や関数呼出回数のカウント.

static 関数は,すべて(1)だぞ,と.
(1) については,Perl の my と同じだぞ,と.
Referrer (Inside): [2005-11-24-1]

C プログラミング診断室 (と 愚痴)
2005-10-31-1 / カテゴリ: [diary][c][] / [permlink]

模様替えの影響で,テレビのアンテナケーブルがテレビまで届かなくなってしまったので, DICE のさくらやに買いに行く.ついでにあおい書店によって,C 本追加.「C プログラミング診断室」
[2005-10-08-1]の「Perl プログラミング救命病棟」と趣旨は近いかな.まぁ,より設計時コーディング時に気をつけることという点ではあるけど.つーか,こっちの本はかなり昔からある良書らしいけど(だから買ったわけだけど^^).
(部課内に)師匠も教材もついでに仲間も上下の手厚いサポートも(以下とりとめもなく延々続きそうなので略,というより続けることができるので自主規制)存在しない今の会社じゃ基礎勉強は書籍や Web だけが頼りだ…つーかもう精神的にというより生理的に限界.と言い続けて早半年だな… 5月は(騙されて)決心鈍ってたけど(笑)
一つはっきりしているのは,魂が(BLEACH風)今の会社に合わない.

今週,仕事中に吐いて倒れそうになって早退したのは,自分にとって事務処理のためだけに存在する上長以外,多分ほとんど誰もしらない :p
そして翌日そのまま休んだことはほとんど誰も気づいていない (ぉ

とりあえず,秋の夜長は設計やコーディングスタイルについてお勉強しよっと.
(…そんな時間があればいいが)

…と,本について,ひとまず忘れたくない名言を.「作らなければ,バグは入らない」

memcpy memset
2005-09-23-2 / カテゴリ: [programming][c] / [permlink]

備忘録
void* memcpy(void *dest, const void *src, size_t count);

src が指してるアドレスから count バイト分を dest へコピーする。
void* memset(void *dest, int c, size_t count);

dest が指してるアドレスから count バイト分を c で埋める。

いつのまにかゴッチャになってて、
memset(p_data, 0, n_datasize);
とすべきところを
memcpy(p_data, 0, n_datasize);
と何箇所も記述していた…
しかも win 上だとエラーになるが、実際に動作させるデバイスではエラーにならんかったので気づかなかった。

メモリのポインタを受け渡しする関数の設計
2005-09-23-1 / カテゴリ: [programming][c] / [permlink]

C言語でポインタを引数に関数を呼び出し、関数での処理結果をそのポインタにセットしてもらうような場合(特に文字列)、

(1) 呼び出し元で初期化して(\0詰等)関数をよびだす
(2) 関数内で初期化して(\0詰め等)処理する



(1) 呼び出し時に有効なメモリのサイズも渡す
(2) サイズは固定で関数内で注意する

あたりに気をつける。
というか、共通の設計思想でコーディングする。

汎用的という点では、前者は (1) 後者も (1)
memcpy やら strncpy なんかのように。

と、今日教わった。
今の会社じゃ誰も教えてくれないこと…

先頭の1文字を消す
2005-09-14-2 / カテゴリ: [programming][c] / [permlink]

memmove を使う
char string[] = "foobarbaz";
memmove(string, string + 1, strlen(string));
これで、[string + 1] から [strlen(string)] バイト分を [string] へコピーする。
つまり、"oobarbaz[NULL]" を f のところへコピーする。
memcpy と異なり、第一引数と第二引数が重なっていても正しく動く。

末尾を消すなら、消したいところで '\0' をいれればいい。

int の 0-9 を char の '0'-'9' に
2005-09-09-1 / カテゴリ: [programming][c] / [permlink]

ch_number = int_number + '0';
int_number が 10以上の場合は、もちろんズレる:p
9(57/0x39)以降は、':', ';', '<', '=', '>', '?', ... と特に脈略はない(ように見える)

逆変換は '0' を引く。もしくは atoi で。

bcc でWindowsプログラミングのコンパイル
2005-08-01-1 / カテゴリ: [win][programming][c] / [permlink]

hmiyazaki@chaource:~/work/prog/win/practice$ bcc base.c 
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
base.c:
警告 W8057 base.c 31: パラメータ 'hPrevInst' は一度も使用されない(関数 WinMain )
警告 W8057 base.c 31: パラメータ 'lpsCmdLine' は一度も使用されない(関数 WinMain )
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: 外部シンボル '_main' が未解決(C:\BORLAND\BCC55\LIB\C0X32.OBJ が参照)

これは -W オプションを付けてコンパイルする。
hmiyazaki@chaource:~/work/prog/win/practice$ bcc -W base.c 
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
base.c:
警告 W8057 base.c 31: パラメータ 'hPrevInst' は一度も使用されない(関数 WinMain )
警告 W8057 base.c 31: パラメータ 'lpsCmdLine' は一度も使用されない(関数 WinMain )
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

VisualStudio買おうかな。いや、でも、うーん…
Referrer (Inside): [2007-03-14-1]

printf(char*)と printf("%s", char*)の違い
2005-05-28-1 / カテゴリ: [c][perl][programming] / [permlink]

(いや、チョー基本的なことなんだろうケド)
char* の中身に % が含まれていたときに意図した動きをしない。

…あ、Perl もだ。printf なんてほとんど使わないから気づかんかった。

source のインストール
2005-05-27-3 / カテゴリ: [win][c][programming][cygwin] / [permlink]

インストーラのパッケージ選択画面で、Source を選択すると、/usr/src/package-version 以下にダウンロードされる。

お勉強用に、more(1) のソースを眺める。割と面白い。more.c しかないのが敷居が低くて良いかも。

rewind と fseek(先頭)の違い
2005-05-26-2 / カテゴリ: [programming][c] / [permlink]

rewind では、FILEオブジェクトが保持している、ファイルopen後のエラーの状態(ferrorで取得できる状態->ファイルエラー指示子)をクリアした上で、先頭へ移動する。
先頭への移動そのものは、fseek(FILE*, 0L, SEEK_SET)と同じ。

独習C 読破
2005-05-26-1 / カテゴリ: [programming][c][diary][] / [permlink]

買って5日なのに…速いって。もったいない…。
ここ最近、通勤電車中でプログラミングの本ばっか読んでるなぁ。ポインタが理解できない理由も読破したのは電車の中だったし。
けど、「本を読む」量は多いけど、「コードを書く」量が少ないのは問題…。電車の中でコードを書くのは…できなくもないけど。座ってるから。どうしよっかな。

はやくハリーポッター文庫版の続き、出ないかなぁ
カテゴリ: c / 前ページ 1 2 3 次ページ

最終更新時間: 2013-05-02 16:12