MW211 EXIT

devlog
C/フォーマット指定子
2012年11月06日
入力系フォーマット指定子
┌──┬───────────────────────────────────┐
│%c  │char型                                                                │
│%s  │文字列                                                                │
├──┼───────────────────────────────────┤
│%d  │整数(10進・符号あり)                                                  │
│%u  │整数(10進・符号なし)                                                  │
│%o  │整数( 8進)                                                            │
│%x  │整数(16進)                                                            │
├──┼───────────────────────────────────┤
│%ld │long型整数(10進・符号あり)                                            │
│%lu │long型整数(10進・符号なし)                                            │
│%lo │long型整数( 8進)                                                      │
│%lx │long型整数(16進)                                                      │
├──┼───────────────────────────────────┤
│%f  │小数                                                                  │
│%lf │double型小数                                                          │
└──┴───────────────────────────────────┘
他に「%e」「%g」もある

出力系フォーマット指定子
┌──┬───────────────────────────────────┐
│%c  │char型                                                                │
│%s  │文字列                                                                │
├──┼───────────────────────────────────┤
│%d  │整数(10進・符号あり)                                                  │
│%u  │整数(10進・符号なし)                                                  │
│%o  │整数( 8進)                                                            │
│%x  │整数(16進)                                                            │
├──┼───────────────────────────────────┤
│%hhd│char型整数(10進・符号あり)                                            │
│%hhu│char型整数(10進・符号なし)                                            │
├──┼───────────────────────────────────┤
│%hd │short型整数(10進・符号あり)                                           │
│%hu │short型整数(10進・符号なし)                                           │
├──┼───────────────────────────────────┤
│%ld │long型整数(10進・符号あり)                                            │
│%lu │long型整数(10進・符号なし)                                            │
│%lo │long型整数( 8進)                                                      │
│%lx │long型整数(16進)                                                      │
├──┼───────────────────────────────────┤
│%f  │小数                                                                  │
│%lf │double型小数                                                          │
└──┴───────────────────────────────────┘
分類:C/C++
C/【未解決】strlen()の柔軟性
2012年11月04日
やみくもに「strlen()」を使っていいものか?

末尾の「\0」を探してサイズを算出してくれるんなら
多少大目にサイズが算出されてもいいんじゃない?
#自分の領域にうっかり「\0」がなくても、
  となりの領域に「\0」があればそこまでのサイズを算出してくれそうだし。。。

でも、莫大なサイズだったらどうしよう?
#ってそんなに「\0」が続かない領域ってあるの?

っていうかたまたま全領域の末尾だったら「\0」がなくてってこともありうるなぁ
#全領域の末尾あたりで作業することってそんなにあるのかな?

ってなことを考えた。

もし仮に、「strlen()」をやみくもに使っていいのであれば、
なんだか出自の知れないポインタをとりあえず「strlen()」でサイズを計ってから
処理するってこともできるし。。。

でも、となりの領域に侵入した時点でアウトみたい。
#でも、実験したら場合によりけりみたいだけど(結論的にはアウトなんでしょう)。

正確な情報を知りたいものだ。
分類:C/C++、【未解決】
C言語/文字列のコピー(2)
2012年10月23日
もう少し踏み込んで条件分岐されるならこんな感じか。
┌──────────────────────────────────────┐
│if (strlen(入力元) < sizeof(出力先)) {                                      │
│    strcpy(出力先, 入力元);                                                 │
│} else {                                                                    │
│    snprintf(出力先, sizeof(出力先), "%s", 入力元);                         │
│}                                                                           │
└──────────────────────────────────────┘
出力先は末尾の「\0」も含んだバッファサイズ(sizeof())で算出し
入力元はあくまで文字数(strlen)。
「文字数+\0≦バッファサイズ」つまり「文字数<バッファサイズ」なら
strcpy()を発動してしまってよいということになる。
分類:C/C++
C言語/文字列のコピー(1)
2012年10月22日
┌──────────────────────────────────────┐
│strncpy(出力先, 入力元, sizeof(出力先) - 1);                                │
└──────────────────────────────────────┘
strncpy()の代わりにsnprintf()も使える。
┌──────────────────────────────────────┐
│snprintf(出力先, sizeof(出力先), "%s", 入力元);                             │
└──────────────────────────────────────┘
これだと確実に末尾に「\0」を押し込めてくれる(多少速度が犠牲になるが)。
分類:C/C++
C言語/アライメントサイズの確認
2012年10月20日
アライメントサイズはコンパイラによって定義されているようだが
その実体定義の場所がわからない。

えいっ、こうなったら実地テストだ、ってのが以下。

char型の次にint型を置いた構造体を用意して、sizeof()で長さを計る。
┌──────────────────────────────────────┐
│struct {                                                                    │
│    char  a;                                                                │
│    int   b;                                                                │
│} z;                                                                        │
│printf("%d", sizeof(z));                                                    │
└──────────────────────────────────────┘
アライメントがなければ(「1」ならば)、「1+4=5」なわけだが、
結果が「8」だった。
つまり、「8=4+4」。
そうアライメントは「4」だ。
分類:C/C++
C言語/文字列のアドレスをダンプする
2012年10月19日
┌──────────────────────────────────────┐
│char str[16];                                                               │
│sprintf("%s", str);                                                         │
└──────────────────────────────────────┘
文字列のアドレスをダンプする方法。

┌──────────────────────────────────────┐
│sprintf("%x", (unsigned int)str);                                           │
└──────────────────────────────────────┘
「%s」を「%x」に切り替えて、「unsigned int」型にキャストするだけ。
分類:C/C++
C言語/define定義の落とし穴
2012年10月18日
┌──────────────────────────────────────┐
│#define    A    2                                                           │
│B = A * 3;        → 2 * 3                → 「6」                          │
└──────────────────────────────────────┘
を想定したとして…。

define定義中で数式を使うのは注意が必要。
┌──────────────────────────────────────┐
│#define    A    1 + 1                                                       │
│B = A * 3;        → 1 + 1 * 3 → 1 + 3   → 「4」                          │
└──────────────────────────────────────┘
そのまま文字列置換のように展開されてしまうので、
加減剰余の優先度によっては意図しない結果となる。

よって、優先度の低い加減が絡む場合には括弧で囲った方がよいようだ
┌──────────────────────────────────────┐
│#define    A    (1 + 1)                                                     │
│B = A * 3;        → (1 + 1) * 3 → 2 * 3 → 「6」                          │
└──────────────────────────────────────┘
分類:C/C++
C/文字列のコピー
2012年10月17日
┌──────────────────────────────────────┐
│char    *in;                                                                │
│char    out[16];                                                            │
└──────────────────────────────────────┘
出力文字列が配列でサイズが決まっているが、
入力文字列がポインタでサイズがわからない場合に、コピーする方法。(in→out)

入力サイズが大きすぎて、末尾のNULL(\0)が落ちてしまうと例外の元になる。

「入力サイズ≦出力サイズ」がある程度保証されているのであれば、
strcpy()を使ってしまえばよい。
┌──────────────────────────────────────┐
│if (strlen(in) < sizeof(out)) {                                             │
│    strcpy(out, in);                                                        │
│}                                                                           │
└──────────────────────────────────────┘
strlen()のサイズと末尾の\0を足したサイズがsizeof()より大きくなってはいけないので
「<=」ではなく「<」である点に注意。

サイズいっぱいにぎりぎりまでコピーしたい場合は、strncpy()を使う。
┌──────────────────────────────────────┐
│memset(out, 0, sizeof(out));                                                │
│strncpy(out, in, sizeof(out) - 1);                                          │
└──────────────────────────────────────┘
末尾の\0分引いたサイズをコピーすることになる。
また、末尾が\0であることを保証するために、直前に\0(0)で全クリアが必要だ。
分類:C/C++
C言語/文字列の自家生成
2012年10月14日
自前で文字列を生成してそのポインタを返却する関数があった場合、
返却する文字列の実体は「static変数」にしておかなければならない。
なぜなら、関数が終了した時点で、実体がなくなってしまうからである。
┌──────────────────────────────────────┐
│const char*  getStr(void) {                                                 │
│    static const char  str[4];                                              │
│    sprintf(str, "%s", "abc");                                              │
│    return str;                                                             │
│}                                                                           │
└──────────────────────────────────────┘
但し、ポインタアドレスを中継するだけならば、「static変数」でなくてもよい。
┌──────────────────────────────────────┐
│const char*  getStr(void) {                                                 │
│    const char*  str;                                                       │
│    getSub(str);  // 文字列のアドレスが返却される                           │
│    return str;                                                             │
│}                                                                           │
└──────────────────────────────────────┘
なので、こんな感じで初期化したりできる。
┌──────────────────────────────────────┐
│const char*  getStr(void) {                                                 │
│    const char*  str = "";  // 初期化                                       │
│    getSub(str);  // 文字列のアドレスが返却される                           │
│    return str;                                                             │
│}                                                                           │
└──────────────────────────────────────┘
極端な話、以下のようなものもOKだ。
┌──────────────────────────────────────┐
│const char*  getStr(void) {                                                 │
│    const char*  str = "xyz";                                               │
│    return str;                                                             │
│}                                                                           │
└──────────────────────────────────────┘
文字列リテラル(上記の例では"abc")は、無条件でstaticでconstなものになるらしい。
┌──────────────────────────────────────┐
│const char*  getStr(void) {                                                 │
│    static const char*  str = "abc";                                        │
│    return str;                                                             │
│}                                                                           │
└──────────────────────────────────────┘
分類:C/C++
C言語/ポインタのキャスト
2012年10月13日
ポインタをキャストする場合、(括弧の中にあるとはいえ)前方に「*」があるので、
実体値となってしまうような錯覚をするがそれはない。

ポインタ「int* a;」を「b = (unsigned int*)a;」のようにキャストした場合、
「b」にはアドレスが代入される(「*a」ではない)。
つまり「unsigned int* b;」と定義しておかなければならない。
「int c;」に代入したい場合には、「c = *a;」、
「unsigned int d;」に代入したい場合には「d = *((unsigned int*)a);」だ。
┌──────────────────────────────────────┐
│int*           a;                                                           │
│unsigned int*  b = (unsigned int*)a;                                        │
│int            c = *a;                                                      │
│unsigned int   d = *((unsigned int*)a);                                     │
└──────────────────────────────────────┘
分類:C/C++
前へ 1 2 3 4 5 6 7 8 9 次へ