#include <vector>
std::vector<std::vector<int>> hoge;
error: '>>' should be '> >' within a nested template argument list
">>"
と
">"
2 個は別だからね。'>'
が予測されるときは、後に何が続いていても '>'
とみなす(">>", ">>=",
">="
が該当)。GCC ならオプション
-std=c++0x
もしくは -std=gnu++0x
でサポート。template<typename F, typename F f> int TmplFunc(int n) { return f(n); }
template<typename F, F f>
class Hoge;
だけ宣言した後、別の class 内
template で Hoge
のメンバを使うと、
それだけで前方参照エラーになるコンパイラと通るコンパイラがある。template
の解析アルゴリズムが違うんだなぁ。困ったもんだ。sample.cpp
#include <cstdio> // エラー回避用 // template<class T> void AnyPrint(T *p) { p->Print(); } class Hoge; class Foo { public: Hoge *GetPtr() { return m_pHoge; } void SetPtr(Hoge *p) { m_pHoge = p; } template<class T> void Func() { GetPtr()->Print(); // AnyPrint<T>(GetPtr()); // こうすると通る // } private: Hoge *m_pHoge; }; class Hoge { public: void Print() { printf("hoge\n"); } }; int main() { Foo foo; Hoge hoge; foo.SetPtr(&hoge); foo.Func<Hoge>(); return 0; }
sprintf(tmp_fname, fname);
tmp_fname
のサイズが足りない場合)」と、「fname
に '%'
が含まれている場合」の 2
つ。どっちもかなり危険。基本だけど、寝ボケてるとやらかしそう。sprintf(tmp_fname, "%.255s", fname);
sprintf_s()
とか std::string
を使う(C++)とかいろいろあるけど、それぞれ一長一短なので、
まぁ状況によって使い分けかな。char tmp_fname[0x10000];
などと巨大な配列をローカル変数にすると、スタックを大量消費するので危険。
static
にすればスタックは使用しなくなるけど、
再帰/再入不可になりがち。objdump
と
stackcheck.pl
(ちょこっと改造)。ググって。char s[30001]
に、
"abc"
を 1 万個つなげた文字列を格納せよ。
ただしなるべく見やすいコードで高速に。char s[30001] = "abcabcabcabcabc
(以下略)は速いけど猛烈に見づらいので却下。
言うまでもないかw ようするにループで処理せよ、と。int i; s[0] = 0; for(i = 0; i < 10000; i++) { strcat(s, "abc"); }
strcat()
が文字列の終端を探すので、長くなるほど遅くなる。size_t len = 0; for(i = 0; i < 10000; i++) { strcpy(&s[len], "abc"); len += strlen("abc"); }
std::string s; for(i = 0; i < 10000; i++) { s += "abc"; }
s = s + "abc";
と書いてしまうと激遅なので注意。"abc" x 10000;
、PHP なら
str_repeat("abc", 10000);
で生成できる。便利。BOOST_PP_REPEAT
マクロで 256
個までなら展開できるようだけど、1 万個は厳しい。
できたとしても実行バイナリがでかくなる上に、
プリプロセッサ出力が大変なことになるので、おすすめできない。int i; for(i = 0; i < (int)strlen(s); i++) { if (s[i] == '*') break; } printf("%d\n", i);
strlen(s)
を呼び出しているので遅い……かもしれない。ループ内で s
を書き換えてないので、最適化すればループの前に出されるかも。
出されないかも。コンパイラ次第。len = strlen(s);
などとループの前に出すか、strlen()
を使わずにポインタで処理するなど。速い CPU
で開発していると、こういう無駄な処理に気付きにくいね。
ループ内の処理にはちょっと気を遣おう。printf("%d\n", -0x80000000 / -0x40000000);
0
。-0x80000000
は unsigned
の
0x80000000
と見なされちゃうのだ。怖いね~。
-0x7fffffff
までは signed
のまま。unsigned int
と signed int
の演算は
unsigned int
に揃えられるので、-0x40000000
は 0xc0000000
になる。結局
0x80000000 / 0xc0000000
となって、整数除算だから
0
。符号付きの値を代入する変数は、符号付き型にキャストしなければなりません。 負の整数定数が符号なしの型に変換されました。
unary minus operator applied to unsigned type, result still unsigned
符号なしの値に負号が適用されましたが、結果は符号なしのままです。
-2147483648
なら、this decimal constant is unsigned only in ISO C90
int a = -0x80000000; printf("%d\n", a / -0x40000000);
2
になる。念のため。unsigned short a = -1, b = -1; printf("%d\n", a * b);
int
が
16bit の環境とか完全無視(ぉぃ)。-131071
。(int)0xffff * (int)0xffff
だね。short
や char
などの演算は、まず
int
に変換される。unsigned short a = -1;
で警告が出ないのは、-0x8000~0xffff
に収まっているから。と言っても VC++ と GCC での話で、C
言語の掟かどうかは知らない(ぉぃ)。printf("%d %d\n", -5 << 2, -255 >> 4);
-20
と -16
……と言いたいところだけど、実は負の数の場合、左シフトの挙動は未定義、
右シフトは処理系依存なのだ。<< 2
」は
「* 4
」と同じになるけど、「>> 4
」
は負の数に対しては「/ 16
」とは少し違う。たとえば
-255 >> 4
は -16
、-255 / 16
は -15
。マイナス無限大方向丸めと、0 方向丸めの違い。a << b
や a >> b
において、b
は 0~(a のビット数 - 1) の範囲じゃないとダメ。
処理系によっては 10 >> -1
を 20
にしてくれたりするけど、移植性無し。double
型から整数部と小数部を別々に取り出したいときに、
どう書けばスマートになるかなぁ‥‥」という質問。xi = (x >= 0.0) ? floor(x) : ceil(x); xf = x - xi;
xf = fmod(x, 1.0);
は重そう。printf("%d\n", 1+~-1["hoge"]);
111
('o'
の ASCII コード)。char str[]="hoge"; printf("%d\n", 1+~-str[1]);
a[b]
は a
と b
がポインタと整数の組み合わせなら *((a) + (b))
と同じ、というのを知らないとわかんないね。
知ってても役に立たないけどねw1+~x = -x
だから、1+~-x = x
。
これはプログラマなら理解してほしいところだけど、ちと難しいかも。double a; a = 0 / 0; printf("%g\n", a);
nan
と表示される」は間違い。整数除算だからね。
某所で気になったので念のため。\n
」「\t
」など)に、
なんで「\?
」(「?
」だけになる)
があるのかと思ったら、トライグラフのせいか。int foo(int x[3]) { return (int)sizeof(x); }
int a[3]; printf("%d %d\n", sizeof(a), foo(a));
12
と 4
。
まぁ細かいことは気にすんな(ぉぃ)。
では後者を 12
にするにはどうすればいい?
return (int)sizeof(int) * 3;
typedef struct { int x[3]; } hoge_t;
int foo(int (&x)[3])
sizeof
で取得できる。
これならスッキリかな~。&x
に括弧付けないとエラーになるから注意。unsigned int a[2] = {1, 2}; int *p = (int *)(&a + 1); printf("%d\n", *(p - 1));
2
。「a
」でなく「&a
」
だと配列全体へのポインタになり、&a + 1
は配列の直後のアドレスになる。http://gcc.gnu.org/gcc-4.5/cxx0x_status.html
cin >> string; cout << string << endl;
>> , <<
」ってどういう仕組み?
という質問があった。Google でうまく検索できなかった模様。
記号は検索できないんだよね。残念。「演算子オーバーロード」でググろう。//
コメントの最後に「表」「能」などの 2 バイト目が
0x5c
(バックスラッシュに相当)の文字がある場合。SJIS
非対応だと次の行につながって、次の行もコメントとみなされてしまう。
かなりヤバい。x++;
」と「++x;
」では、
「++x;
」のほうが速いことが多い。x++;
」は「x
を退避して、++
の処理をして、退避した x
を返す」ので、退避する手間がかかるため。