したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | メール | |

管理人の独り言(プログラミング関連)

1みみず★:2008/08/10(日) 23:28:15
あまりにもプログラミングの内容が増えすぎた。
よって隔離スレの中を更に隔離。

202 ◆rCEzuNnL0g:2008/09/02(火) 21:38:44
今度は解説を読まずにやろう!
時間もちゃんと計ってね。

203 ◆rCEzuNnL0g:2008/09/02(火) 23:05:39
2007年度の俺の答え
1:>>191
2:>>192
3:>>194
4:>>196
5:まだ無い

204 ◆rCEzuNnL0g:2008/09/02(火) 23:08:00
4:は解説を見た
5:も解説を見てやろう。

205 ◆rCEzuNnL0g:2008/09/02(火) 23:19:46
C言語入門
http://www5c.biglobe.ne.jp/~ecb/c/c00.html
で、ファイルの操作について詳しく勉強する。
C++のファイル操作もkwskやりたい。

206 ◆rCEzuNnL0g:2008/09/02(火) 23:21:47
FrontPage - プログラミングTipsWiki - livedoor Wiki(ウィキ)
http://wiki.livedoor.jp/eruvasu/d/FrontPage

207 ◆rCEzuNnL0g:2008/09/02(火) 23:28:42
C++で一行ずつ文字列を取得する方法。他にもある?
------
stl_fstream - プログラミングTipsWiki - livedoor Wiki(ウィキ)
http://wiki.livedoor.jp/eruvasu/d/stl_fstream?wiki_id=62368

208 ◆rCEzuNnL0g:2008/09/03(水) 00:56:15
という事で、基本を押さえよう。std::名前空間。
因みに2007ねんのもんだいはおもいつけばなんとかなるとおもった。

まあ、1%の閃きと99%の努力だからなあ。
1%の閃きが重要なんだよな。
現実は厳しい。

209 ◆rCEzuNnL0g:2008/09/03(水) 18:26:03
Google Chrome入れた。
やっぱり軽い。
JavaScriptのコンソールも良い感じ。
だけれども常用には耐えかねる。

210 ◆rCEzuNnL0g:2008/09/03(水) 18:29:23
こんな風にしたら、ちゃんとインライン展開された!

#include <iostream>

template<unsigned int c>
void Call(void (__cdecl pf)(int)){
Call<c - 1>(pf);
pf(c);
}

template<>
void Call<0>(void (__cdecl pf)(int)){
return;
}

void test(int c){
__asm{
push eax
pop eax
}
}

int main(int argc, char **argv){
Call<10>(test);
}

211 ◆rCEzuNnL0g:2008/09/03(水) 18:31:14
これは展開されない!
testは同じね。
-----
int main(int argc, char **argv){
for(int i = 0; i < 10; ++i)
test(i);
}

212 ◆rCEzuNnL0g:2008/09/03(水) 18:33:22
まあ、使えるのは10までっぽい。

213 ◆rCEzuNnL0g:2008/09/03(水) 18:55:52
まあ、十三ぐらいまではいけると思うけれども、あんまり宜しくないかも。

10.765/11.281/11.063/10.422 <-インライン展開
11.063/10.531/9.719/11.078 <-通常

ん?
インライン展開されて、比較の回数が減っているはずなのに遅いぜwww

-----
#include <iostream>
#include <ctime>

template<unsigned int c>
void Call(void (__cdecl pf)(int)){
Call<c - 1>(pf);
pf(c);
}

template<>
void Call<0>(void (__cdecl pf)(int)){
return;
}

void test(int c){
std::cout << c << std::endl;
}

int main(int argc, char **argv){
clock_t s = clock();

for(int i = 0; i < 10000; i++){
Call<10>(test);
/*
for(int i = 1; i <= 10; i++){
test(i);
}
*/
}

clock_t e = clock();

std::cout << (double)(e - s) / CLOCKS_PER_SEC << std::endl;
}

214 ◆rCEzuNnL0g:2008/09/03(水) 22:15:44
恐らくだけれどもCPUのキャッシュの問題だと思う。
第一次キャッシュがそんなにも大きくないのだろう。

215 ◆rCEzuNnL0g:2008/09/03(水) 22:30:23
本選第三問はオーバーフローに対する問題であろう。
つまり、大体は総当りでやればいいのだが、その時にどのように比較するかというのが重要である。
つまり
今まで足したの+今回足すの>規定の値
でやっていたら、左の値がオーバーフローしたら駄目である。
よって条件を、
今まで足したの>規定の値−今回足すの

今回足すの>規定の値−今まで足したの
にしなければならない。
まあ、与えられた値を降順(昇順)に並び替えるのも重要だよね。
降順だったら、一番大きいのを足して、次にまた足して、また足してを繰り返して、
規定の値を越えることとなったら、段々と小さい値を足していく。
そしてそれが終わったら、一個分戻って次に小さい値を試してその値から順番に小さい値を試していく。
そして、規定の値を超えない奴があったら、それと前回の奴を比較して大きいほうを取ると。
まあ、それの繰り返しで良いと思う。
Nの値は十分に小さいから、スタックは足りるはず。

216 ◆rCEzuNnL0g:2008/09/03(水) 22:32:33
多分解けるね。
再帰的呼び出しの問題だな、っと。

217 ◆rCEzuNnL0g:2008/09/03(水) 22:38:54
"やらにゃーか" 倉庫 - Google 検索
http://www.google.co.jp/search?hl=ja&amp;q=%22%E3%82%84%E3%82%89%E3%81%AB%E3%82%83%E3%83%BC%E3%81%8B%22+%E5%80%89%E5%BA%AB&amp;lr=
---
一件だけww

218 ◆rCEzuNnL0g:2008/09/03(水) 22:49:07
これ間違ってます。
これ間違ってます。

一問目について。
必要な変数は、いま連続している色、連続している個数、現在のインデックス、変更できるか、白の個数。
まず一個目は、
いま連続している色=今見ている色
連続している個数=1
現在のインデックス=1
変更できるか=出来ない
白の個数=現在の色が白なら1じゃないなら0
を代入する。
以下ループ
現在のインデックスをインクリメント
現在のインデックスが奇数の時
 現在見ている色と今の色が同じの時連続している個数をインクリメント
 違うとき今見ている色を変えて連続している個数=1。変更できるかが出来ないときは出来るを代入
現在のインデックスが偶数の時
 現在見ている色と今の色が同じの時連続している個数をインクリメント
 違うときがちょっと複雑
  変更できるかが出来ないとき現在見ている色を変えて連続している個数=1。変更できるかを変更できるへ。
  変更できるかが出来るとき
   今見ている色が黒の時白の個数

219 ◆rCEzuNnL0g:2008/09/03(水) 22:58:26
>>218
普通にメモリが確保できた件について。
まあ、実際に採点が行われるパソコンで確保できるかは疑問だが。
というか、一番最初から違うのが出るまでは読み飛ばして良いと思う。
なぜかというとひっくり返しようが無いから。
0000001となっていたら、初めの六つの0は絶対ひっくり返らない。
だから
00000だけは読み飛ばして、
01
に色々とくっつけて考える。
0を白とするならば、その数だけ覚えておけばいい。これでは5.

220 ◆rCEzuNnL0g:2008/09/03(水) 22:59:40
で、次に最初に来る色と、今見ているインデックス(最初に読み飛ばしたのも入れて)、今見ている色が分かれば良い。

221 ◆rCEzuNnL0g:2008/09/03(水) 23:01:08
ああ、やっぱり場合分けが面倒だなあ。全部動的にメモリ確保してやったほうが早くね?

222 ◆rCEzuNnL0g:2008/09/03(水) 23:04:06
まあ、実際にはそんなに時間は無いのだが、良く考えてみよう。
寝る。

223 ◆rCEzuNnL0g:2008/09/04(木) 19:28:42
T216のソースが出たので取り敢えず落とす。
大体五百行ぐらいかなあ?
まあ多くても千行位なので頑張って読めば(ry

224 ◆rCEzuNnL0g:2008/09/04(木) 20:13:11
DbgHelp
http://msdn.microsoft.com/ja-jp/library/cc428915.aspx

225 ◆rCEzuNnL0g:2008/09/04(木) 20:14:08
>>223
こういうの見ていると、Lispを動かせるように何か書きたくなる。
いや、マジで。
書かないけれども。
取り敢えず時間があるときに研究だ!

226 ◆rCEzuNnL0g:2008/09/04(木) 20:35:42
知りたいこと
・GCの実装
・構文解析
・実行の方法

227 ◆rCEzuNnL0g:2008/09/04(木) 20:39:45
ダイナミックObjective-C | コラム | エンタープライズ | マイコミジャーナル
http://journal.mycom.co.jp/column/objc/
---
Objective-C

228 ◆rCEzuNnL0g:2008/09/04(木) 22:28:44
Google Chrome の JavaScript エンジン V8 を試す - IT戦記
http://d.hatena.ne.jp/amachang/20080903/1220405193
-----
V8で何か書く?

229 ◆rCEzuNnL0g:2008/09/04(木) 22:29:20
Standard ECMA-262
http://www.ecma-international.org/publications/standards/Ecma-262.htm
----
ECMA-262仕様書。

230 ◆rCEzuNnL0g:2008/09/04(木) 22:31:33
>>229
どんな感じでスクリプトエンジンを作ればいいかが、わかるかもしれない。

231 ◆rCEzuNnL0g:2008/09/04(木) 22:40:03
SafariとGoogle Chromeとで表示が異なる。
フォントは明らかだが、エレメントの角を丸めたときに周りが黒くなる。
エレメントに影を付けていることかなあ。

232 ◆rCEzuNnL0g:2008/09/05(金) 00:55:43
>>231
エレメントに影を付けていることかなあ。
-> エレメントに影を付けているからかなあ。

233 ◆rCEzuNnL0g:2008/09/05(金) 01:09:01
>>223
今の僕には理解できないww

234 ◆rCEzuNnL0g:2008/09/05(金) 01:09:32
あれ・・・
ただのCなのにな。
なんだか目眩が・・・

235 ◆rCEzuNnL0g:2008/09/05(金) 01:10:04
そういえば、Sleipnirの新バージョンが出たよー。
特に新しくなっていないから、いれなくてもいいんじゃね?

236 ◆rCEzuNnL0g:2008/09/05(金) 19:50:51
SunSpider JavaScript Benchmark Results
http://www2.webkit.org/perf/sunspider-0.9/sunspider-results.html?%7B%223d-cube%22:%5B563,437,453,438,438%5D,%223d-morph%22:%5B516,532,516,438,469%5D,%223d-raytrace%22:%5B532,578,594,562,562%5D,%22access-binary-trees%22:%5B672,1281,1391,1406,1203%5D,%22access-fannkuch%22:%5B907,906,906,922,906%5D,%22access-nbody%22:%5B625,594,640,656,641%5D,%22access-nsieve%22:%5B453,438,359,375,422%5D,%22bitops-3bit-bits-in-byte%22:%5B406,312,390,391,390%5D,%22bitops-bits-in-byte%22:%5B437,391,422,407,407%5D,%22bitops-bitwise-and%22:%5B704,687,687,703,718%5D,%22bitops-nsieve-bits%22:%5B531,515,531,500,500%5D,%22controlflow-recursive%22:%5B344,359,391,421,391%5D,%22crypto-aes%22:%5B547,531,469,594,516%5D,%22crypto-md5%22:%5B203,344,329,204,188%5D,%22crypto-sha1%22:%5B281,297,343,359,375%5D,%22date-format-tofte%22:%5B844,1859,2000,1969,1968%5D,%22date-format-xparb%22:%5B453,453,469,484,469%5D,%22math-cordic%22:%5B485,500,562,484,485%5D,%22math-partial-sums%22:%5B469,437,469,453,469%5D,%22math-spectral-norm%22:%5B406,422,438,422,391%5D,%22regexp-dna%22:%5B500,609,500,500,485%5D,%22string-base64%22:%5B1688,1781,1687,1735,1766%5D,%22string-fasta%22:%5B438,422,422,438,437%5D,%22string-tagcloud%22:%5B344,484,344,343,343%5D,%22string-unpack-code%22:%5B344,344,328,454,343%5D,%22string-validate-input%22:%5B531,484,469,500,500%5D%7D

237 ◆rCEzuNnL0g:2008/09/05(金) 21:42:41
CPUのセグメントについて勉強したい。

238 ◆rCEzuNnL0g:2008/09/06(土) 13:27:50
Cygwinについて勉強するよー
Linuxのコマンドについても知りたいしねw

兄者にC入門以前の本を貸していただきたいものである。
つまりCUIを勉強したいなあと。

239 ◆rCEzuNnL0g:2008/09/06(土) 18:56:31
Linux(Unix)には一ページ出力したら、出力を一時停めるコマンドは無いのか?

240 ◆rCEzuNnL0g:2008/09/06(土) 18:56:50
Windowsならmoreで出来るのだが。

241 ◆rCEzuNnL0g:2008/09/06(土) 21:12:36
C++で、文字列を一行分取得するのは普通に
std::istream::getlineで出来るじゃんと。
-----
char p[100];
std::cin.getline(p, sizeof(p));
-----

242 ◆rCEzuNnL0g:2008/09/06(土) 21:12:52
ファイルストリームもこれまた同様。

243 ◆rCEzuNnL0g:2008/09/06(土) 21:13:39
std::stringだったら
---
std::string str;
std::cin >> str;
でいいんだけれども。空白文字列とか、そこらへんの扱いが良く分からん。

244 ◆rCEzuNnL0g:2008/09/06(土) 22:14:39
typename は何故必要か
http://ray.sakura.ne.jp/template/typename.html
----
クソッ。このサイトに騙された。
typedef typename T type;
とか書かないといけないのに、typedefを省略するな。死んでしまえ!
という事で、忘れないように。

245 ◆rCEzuNnL0g:2008/09/06(土) 22:19:06
テンプレートメタプログラミングで多次元配列を返す関数を実装したい。
という事で、取り敢えず返却する型を返すプログラムを書いた。
---
template<typename t>
struct Pointer{
template<size_t i>
struct _{
typedef typename Pointer<t>::_<i - 1>::type *type;
};

template<>
struct _<0>{
typedef typename t type;
};
};

246 ◆rCEzuNnL0g:2008/09/06(土) 22:22:10
Pointer<char>::_<100>::type p;
とかすると“p”の型が
char型へのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへの
ポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタへのポインタ
になる。

247 ◆rCEzuNnL0g:2008/09/06(土) 22:22:50
まあ、正直意味が無いんだけれどもね。
多次元配列には使える。

248 ◆rCEzuNnL0g:2008/09/06(土) 22:50:07
template名前空間なんて無い?
まあ、ただのclassと言ってしまえば(ry

249 ◆rCEzuNnL0g:2008/09/06(土) 22:50:53
こんな特殊化は出来ないのか!
----
template<typename t, size_t i>
typename Pointer<t>::_<i>::type Vec(va_list arg){
typename Pointer<t>::_<i>::type p;
size_t size = va_arg(arg, size_t);
p = new typename Pointer<t>::_<i - 1>[size];
for(int i = 0; i < size; ++i){
p[i] = Vec<t, i - 1>(arg);
}
return p;
}

template<typename t>
typename Pointer<t>::_<1>::type Vec<t, 1>(va_list arg){
return NULL;
}

250 ◆rCEzuNnL0g:2008/09/06(土) 23:16:26
何行目のエラーだよwww
------

------ すべてのリビルド開始: プロジェクト: test_test, 構成: Debug Win32 ------
プロジェクト 'test_test'、構成 'Debug|Win32' の中間出力ファイルを削除しています。
コンパイルしています...
main.cpp
プロジェクト : error PRJ0002 : エラーの結果 -1073741819 が 'C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe' より返されました。
ビルドログは "file://c:\Documents and Settings\*********\My Documents\Visual Studio 2008\Projects\test_test\test_test\Debug\BuildLog.htm" に保存されました。
test_test - エラー 1、警告 0
========== すべてリビルド: 0 正常終了、1 失敗、0 スキップ ==========

251 ◆rCEzuNnL0g:2008/09/06(土) 23:25:43
>>250
-----
#include <iostream>
#include <cstdarg>

template<typename t>
struct Pointer{
template<size_t i>
struct _{
typedef typename Pointer<t>::_<i - 1>::type *type;
};

template<>
struct _<0>{
typedef typename t type;
};
};

template<typename t>
struct _Vec{
template<size_t i>
static
typename Pointer<t>::_<i>::type fnc(va_list arg){
typename Pointer<t>::_<i>::type p;
size_t size = va_arg(arg, size_t);
p = new typename Pointer<t>::_<i - 1>[size];
for(size_t i = 0; i < size; ++i){
p[i] = Vec<t, i - 1>(arg);
}
return p;
}

template<>
static
typename Pointer<t>::_<1>::type fnc<1>(va_list arg){
size_t size = va_arg(arg, size_t)
return new typename Pointer<t>::_<0>::type[size];
}
};

template<typename t, size_t i>
typename Pointer<t>::_<i>::type Vec(size_t size, ...){
va_list arg;
va_start(arg, size);
typename Pointer<t>::_<i>::type p;
p = new typename Pointer<t>::_<i - 1>::type[size];
for(size_t j = 0; j < size; ++j){
p[j] = _Vec<t>::fnc<i - 1>(arg);
}
va_end(arg);

return p;
}

int main(){
Pointer<char>::_<1>::type p = Vec<char, 1>(10, 20);
}

252 ◆rCEzuNnL0g:2008/09/06(土) 23:35:07
出来たー
但しVec<>()のテンプレートの第二引数に1以下の値を渡すとコンパイラが暴走するよ。
----
#include <iostream>
#include <cstdarg>

template<typename t>
struct Pointer{
template<size_t i>
struct _{
typedef typename Pointer<t>::_<i - 1>::type *type;
};

template<>
struct _<0>{
typedef typename t type;
};
};

template<typename t>
struct _Vec{
template<size_t i>
static
typename Pointer<t>::_<i>::type fnc(va_list arg){
typename Pointer<t>::_<i>::type p;
size_t size = va_arg(arg, size_t);
p = new typename Pointer<t>::_<i - 1>::type[size];
for(size_t j = 0; j < size; ++j){
p[j] = fnc<i - 1>(arg);
}
return p;
}

template<>
static
typename Pointer<t>::_<1>::type fnc<1>(va_list arg){
size_t size = va_arg(arg, size_t);
return new typename Pointer<t>::_<0>::type[size];
}
};

template<typename t, size_t i>
typename Pointer<t>::_<i>::type Vec(size_t size, ...){
va_list arg;
va_start(arg, size);
typename Pointer<t>::_<i>::type p;
p = new typename Pointer<t>::_<i - 1>::type[size];
for(size_t j = 0; j < size; ++j){
p[j] = _Vec<t>::fnc<i - 1>(arg);
}
va_end(arg);

return p;
}

int main(){
Pointer<char>::_<10>::type p = Vec<char, 10>(2, 2, 2, 2, 2, 2, 2, 2, 2, 2);
}

253 ◆rCEzuNnL0g:2008/09/06(土) 23:45:19
ぎゃー。
char型の百次元配列を作ろうとしたら止まったwww

254 ◆rCEzuNnL0g:2008/09/06(土) 23:45:48
それに、関係ないブラウザまで落ちたwwww

255 ◆rCEzuNnL0g:2008/09/06(土) 23:47:32
アセンブリの出力のためにコンパイルだけしよう。
実行して落とすしかなくなったら困るし。

256 ◆rCEzuNnL0g:2008/09/06(土) 23:51:00
これはwwww
----
call ??$Vec@D$0GE@@@YAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPADIZZ ; Vec<char,100>

257 ◆rCEzuNnL0g:2008/09/07(日) 00:22:18
テンプレートウマー

258 ◆rCEzuNnL0g:2008/09/07(日) 01:12:29
ジャンケンゲーム - 素人がプログラミングを勉強するブログ
http://d.hatena.ne.jp/javascripter/20080906/1220714829
------
この判別の発想は無いわ。

259 ◆rCEzuNnL0g:2008/09/07(日) 01:20:54
sin,cos,tanとかCの標準関数って、ntdll.dllから提供されているんだなあと。

260 ◆rCEzuNnL0g:2008/09/07(日) 10:36:10
C++で、どのようにして多態性を実現しているのかが分からない。
という事で、アセンブリで眺めているのだが良く分からん。
うわあああ
どっかに解説しているサイトないかなあ。

261 ◆rCEzuNnL0g:2008/09/07(日) 10:41:23
つまり関数ポインタの配列へのポインタを持っているんだよな。
それは分かる。問題は何処に持っているかである。

ん?もしかして、関数ポインタへの配列へのポインタ配列へのポインタを持っているのか?

262 ◆rCEzuNnL0g:2008/09/07(日) 11:14:13
p = &c1;
0041160C lea eax,[ebp-18h]
0041160F mov dword ptr [ebp-34h],eax
p->Set(100);
00411612 mov esi,esp
00411614 push 64h
00411616 mov eax,dword ptr [ebp-34h]
00411619 mov edx,dword ptr [eax]
0041161B mov ecx,dword ptr [ebp-34h]
0041161E mov eax,dword ptr [edx+4]
00411621 call eax
00411623 cmp esi,esp
00411625 call @ILT+500(__RTC_CheckEsp) (4111F9h)

263 ◆rCEzuNnL0g:2008/09/07(日) 11:20:07
ポインタへの代入はただ単に代入しているだけだよなあ。
“ebp-34h”がオブジェクトへのポインタへ。
で、
00411621 call eax
とやっているから、この時点でeaxには関数へのポインタが入っていると。
ということは重要なのは
-----
00411616 mov eax,dword ptr [ebp-34h]
00411619 mov edx,dword ptr [eax]
0041161E mov eax,dword ptr [edx+4]
00411621 call eax
-----
だけか。

264 ◆rCEzuNnL0g:2008/09/07(日) 11:28:20
やっぱり単一継承の時は、クラスの一番アドレスの低いところに関数ポインタの配列へのポインタが入っているっぽい。

265 ◆rCEzuNnL0g:2008/09/07(日) 11:40:37
┌────────┐     ┌────────┐
│CSub1::`vftable'│────→│ 関数ポインタ │
├────────┤     ├────────┤
│  メンバ変数  │     │ 関数ポインタ │
└────────┘     ├────────┤
               │ 関数ポインタ │
               └────────┘

266 ◆rCEzuNnL0g:2008/09/07(日) 11:41:15
予想以上にずれたなあ。
メモ帳にコピーすれば綺麗に見えますよ。

267 ◆rCEzuNnL0g:2008/09/07(日) 11:42:21
結論。
単純継承の場合は何処から継承しているかは分からない。

268 ◆rCEzuNnL0g:2008/09/07(日) 11:52:53
多重継承の場合はそんなに単純ではない。
適当にペンと消しゴムのようなクラスを実装して、
ペンと消しゴムが一緒になったクラスを継承で定義してみる。
-----
CPenWithEraser c;
004115CD lea ecx,[ebp-18h]
004115D0 call CPenWithEraser::CPenWithEraser (411019h)
004115D5 mov dword ptr [ebp-4],0
IPen *pp = &c;
004115DC lea eax,[ebp-18h]
004115DF mov dword ptr [ebp-24h],eax
IEraser *pe = &c;
004115E2 lea eax,[ebp-18h]
004115E5 test eax,eax
004115E7 je main+67h (4115F7h)
004115E9 lea ecx,[ebp-18h]
004115EC add ecx,4
004115EF mov dword ptr [ebp-104h],ecx
004115F5 jmp main+71h (411601h)
004115F7 mov dword ptr [ebp-104h],0
00411601 mov edx,dword ptr [ebp-104h]
00411607 mov dword ptr [ebp-30h],edx
pp->Write("書き書き");
0041160A sub esp,20h
0041160D mov ecx,esp
0041160F mov dword ptr [ebp-0FCh],esp
00411615 mov esi,esp
00411617 push offset string "\x8f\x91\x82\xab\x8f\x91\x82\xab" (417800h)
0041161C call dword ptr [__imp_std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (41B344h)]
00411622 cmp esi,esp
00411624 call @ILT+495(__RTC_CheckEsp) (4111F4h)
00411629 mov dword ptr [ebp-104h],eax
0041162F mov eax,dword ptr [ebp-24h]
00411632 mov edx,dword ptr [eax]
00411634 mov ecx,dword ptr [ebp-24h]
00411637 mov eax,dword ptr [edx]
00411639 call eax
pe->Erase();
0041163B mov eax,dword ptr [ebp-30h]
0041163E mov edx,dword ptr [eax]
00411640 mov esi,esp
00411642 mov ecx,dword ptr [ebp-30h]
00411645 mov eax,dword ptr [edx]
00411647 call eax
00411649 cmp esi,esp
0041164B call @ILT+495(__RTC_CheckEsp) (4111F4h)
-----

269 ◆rCEzuNnL0g:2008/09/07(日) 11:54:19
IPen*へのダウンキャストは、ただ単にポインタを代入しているだけだが、
IEraser*へのダウンキャストは、ちょっと複雑なようだ。
そこらへんをピックアップ。

270 ◆rCEzuNnL0g:2008/09/07(日) 11:55:03
IEraser *pe = &c;
004115E2 lea eax,[ebp-18h]
004115E5 test eax,eax
004115E7 je main+67h (4115F7h)
004115E9 lea ecx,[ebp-18h]
004115EC add ecx,4
004115EF mov dword ptr [ebp-104h],ecx
004115F5 jmp main+71h (411601h)
004115F7 mov dword ptr [ebp-104h],0
00411601 mov edx,dword ptr [ebp-104h]
00411607 mov dword ptr [ebp-30h],edx

271 ◆rCEzuNnL0g:2008/09/07(日) 12:12:49
ebp-104hが良く分からないが、大体構造は以下のようである。
┌─────────────┐
│CPenWithEraser::`vftable' │←IPenの関数ポインタ配列へのポインタ
├─────────────┤
│CPenWithEraser::`vftable' │←IEraserの関数ポインタ配列へのポインタ
└─────────────┘

272 ◆rCEzuNnL0g:2008/09/07(日) 12:20:31
もしもIPenやIEraserがメンバ変数を持っている場合は以下のようになる。
┌─────────────┐
│CPenWithEraser::`vftable' │←IPenの関数ポインタ配列へのポインタ
├─────────────┤
│  IPenのメンバ変数   │
├─────────────┤
│CPenWithEraser::`vftable' │←IEraserの関数ポインタ配列へのポインタ
├─────────────┤
│  IEraserのメンバ変数   │
├─────────────┤
│CPenWithEraserのメンバ変数│
└─────────────┘

273 ◆rCEzuNnL0g:2008/09/07(日) 12:22:59
つまりCPenWithEraserからIEraserへキャストするときは、
IPen用のvftableとメンバ変数分の大きさをポインタに足せばいい。
これは三つから継承しても、四つから継承しても同じ。

274 ◆rCEzuNnL0g:2008/09/07(日) 12:28:34
つまり、多重継承しているときは、ポインタを代入した積もりでも、
ポインタの値は異なっているということである。
上の例では厳密には&c != peである。
ただ、実際に
if(&c == pe){std::cout << "等しい!" << std::endl;}
とやると、&cが(IEraserに)ダウンキャストされてから比較が行われるので、
等しい!と表示される。
という事で、多重継承は遅くなる原因なので必要最低限に留めた方が良いかと。

275 ◆rCEzuNnL0g:2008/09/07(日) 12:30:24
まあ、そんなこと言ったらC++は遅いので使わないほうが良いよ、と言っているようなものだがw

276 ◆rCEzuNnL0g:2008/09/07(日) 12:38:51
これは
IHuman *ph = &c;
でIHumanがISwimmerかIClimberのどちらかが分からないからコンパイルが出来ない。
---
#include <iostream>
#include <string>

class IHuman{
public:
virtual
void
Breath() = 0;
};

class ISwimmer : public IHuman{
public:
virtual
void
Swim() = 0;
};

class IClimber : public IHuman{
public:
virtual
void
Climb() = 0;
};

class CBaka : public ISwimmer, public IClimber{
public:
virtual
void
Breath(){
std::cout << "スースー" << std::endl;
}
virtual
void
Swim(){
std::cout << "ぶくぶくぶく" << std::endl;
}
virtual
void
Climb(){
std::cout << "どっこいしょ" << std::endl;
}
};

int main(int argc, char **argv){
CBaka c;
IHuman *ph = &c;
ph->Breath();
}

277 ◆rCEzuNnL0g:2008/09/07(日) 12:40:46
このように書けばコンパイルが出来る。
があんまり意味がない気がする。
---
#include <iostream>
#include <string>

class IHuman{
public:
virtual
void
Breath() = 0;
};

class ISwimmer : public IHuman{
public:
virtual
void
Swim() = 0;
};

class IClimber : public IHuman{
public:
virtual
void
Climb() = 0;
};

class CBaka : public ISwimmer, public IClimber{
public:
virtual
void
Breath(){
std::cout << "スースー" << std::endl;
}
virtual
void
Swim(){
std::cout << "ぶくぶくぶく" << std::endl;
}
virtual
void
Climb(){
std::cout << "どっこいしょ" << std::endl;
}
};

int main(int argc, char **argv){
CBaka c;
IHuman *ph1 = (ISwimmer *)&c;
IHuman *ph2 = (IClimber *)&c;
ph1->Breath();
ph2->Breath();
}

278 ◆rCEzuNnL0g:2008/09/07(日) 12:46:14
という事で、このようなときのために仮想継承というものがある。
これで良い感じ。
-----
#include <iostream>
#include <string>

class IHuman{
public:
virtual
void
Breath() = 0;
};

class ISwimmer : public virtual IHuman{
public:
virtual
void
Swim() = 0;
};

class IClimber : public virtual IHuman{
public:
virtual
void
Climb() = 0;
};

class CBaka : public ISwimmer, public IClimber{
public:
virtual
void
Breath(){
std::cout << "スースー" << std::endl;
}
virtual
void
Swim(){
std::cout << "ぶくぶくぶく" << std::endl;
}
virtual
void
Climb(){
std::cout << "どっこいしょ" << std::endl;
}
};

int main(int argc, char **argv){
CBaka c;
IHuman *ph = &c;
}

279 ◆rCEzuNnL0g:2008/09/07(日) 12:47:42
因みに、クラス名がCBakaとなっているのは、良い名前が思いつかなかったから。
ただそれだけ。

280 ◆rCEzuNnL0g:2008/09/07(日) 12:50:14
仮想継承するとなんだか更にアセンブリコードが複雑になるなあ。
-----
CBaka c;
0041156E push 1
00411570 lea ecx,[c]
00411573 call CBaka::CBaka (4111EAh)
IHuman *ph = &c;
00411578 lea eax,[c]
0041157B test eax,eax
0041157D jne main+3Bh (41158Bh)
0041157F mov dword ptr [ebp-0ECh],0
00411589 jmp main+4Bh (41159Bh)
0041158B mov ecx,dword ptr [ebp-14h]
0041158E mov edx,dword ptr [ecx+4]
00411591 lea eax,[ebp+edx-14h]
00411595 mov dword ptr [ebp-0ECh],eax
0041159B mov ecx,dword ptr [ebp-0ECh]
004115A1 mov dword ptr [ph],ecx

281 ◆rCEzuNnL0g:2008/09/07(日) 12:52:01
因みにリリース版でビルドするとこんな感じ
-----
int main(int argc, char **argv){
00401090 sub esp,14h
CBaka c;
IHuman *ph = &c;
ph->Breath();
00401093 lea ecx,[esp+10h]
00401097 mov dword ptr [esp+4],offset CBaka::`vbtable' (402180h)
0040109F mov dword ptr [esp+0Ch],offset CBaka::`vbtable' (402188h)
004010A7 mov dword ptr [esp],offset CBaka::`vftable' (40216Ch)
004010AE mov dword ptr [esp+8],offset CBaka::`vftable' (402174h)
004010B6 mov dword ptr [esp+10h],offset CBaka::`vftable' (40217Ch)
004010BE call dword ptr [CBaka::`vftable' (40217Ch)]
}
004010C4 xor eax,eax
004010C6 add esp,14h
004010C9 ret

282 ◆rCEzuNnL0g:2008/09/07(日) 12:55:01
ん!
vbtableってなんだ?vftableなら分かるが・・・

283 ◆rCEzuNnL0g:2008/09/07(日) 13:35:43
仮想継承のコードは複雑すぎて分からない。
が結局のところ、普通の継承と同じような感じだと思っている。
眠たくなってきた。

284 ◆rCEzuNnL0g:2008/09/07(日) 13:58:06
仮想継承で意味があるのはこんなのではない。
本当に意味があるのは、この例ではIHumanにメンバ変数がある時である。
そのときにCBaka*をISwimmer*やIClimber*にダウンキャストして、
ISwimmer::メンバ変数やIClimber::メンバ変数を変更すると、両方に適用されると。
ということは、両方とも同じメンバ変数を参照するためには、色々となんか良く分からないことをやる必要がある。
まあ、実際にやってみたのだが、その補正用の値がvbtableに格納されていると思われる。
恐らくこんな感じのメモリの使われ方ではなかろうか。
+00:CBaka::`vftable' <- ISwimmer
+04:CBaka::`vbtable' <- ISwimmerのIHumanメンバ変数参照用
+08:CBaka::`vftable' <- IClimber
+0C:CBaka::`vbtable' <- IClimberのIHumanメンバ変数参照用
+10:CBaka::`vftable' <- IHuman

285 ◆rCEzuNnL0g:2008/09/07(日) 13:59:11
ISwimmerやIClimberにメンバ変数が入った場合は、
普通にvbtableの後にそれぞれ場所をとれば大丈夫である。
本当に最初に此れを考えた奴は天才だなあ。

286 ◆rCEzuNnL0g:2008/09/07(日) 14:01:46
CBakaのメンバ変数はIHumanのメンバ変数の後に追加すればよい。
IHumanのメンバ変数はvftableの後に追加すればよい。
こうすればIHumanを仮想継承していないクラスがあったとしても、
IHumanのメンバ関数は通常通りに読み出せる。

vbtableはISwimmer*からIHumanやIClimberからIHumanへのキャストへも使われる予感。

287 ◆rCEzuNnL0g:2008/09/07(日) 14:06:16
仮想継承をしたら、仮想継承したクラスはvbtableを持たねばなるまい。
例えそのクラスを他のクラスに継承しなくても、仮想継承汁!とソースに書かれている以上、用意はせねばいかん。
という事で、必要な時意外は、遅くなる仮想継承は止めましょうということです。

288 ◆rCEzuNnL0g:2008/09/07(日) 14:16:54
そういえば、コンストラクタが返す値は
自分自身の参照。
何故ならば
std::string("Yahoo!!").c_str();
という書き方が出来るから。
ポインタだと->演算しだし、参照じゃないと無駄が多い。
という事で参照。

289 ◆rCEzuNnL0g:2008/09/07(日) 14:29:22
某所でキャストの仕方について次のような奴があった。
type(...)
つまり
char c = '3';
std::cout << int(c) << std::endl;
の後の奴を型キャストとか言っている訳だ。
うん実際に試せば分かるが此れは“51”と出力される。普通に出力すると“3”である。
ただ、此れは厳密にはキャストではなくて、int型のコンストラクタが呼ばれているだけである。
つまり、int型やchar型云々にもデフォルトでコンストラクタがあるということである。
実際に以下のコードを試すと“0”と出力される。
---
std::cout << int() << std::endl;
---
勿論char()にすれば何も表示されない(何故ならば、NULL文字だから)。
試していないが、その他unsigned int()とかwchar_t()とかでも同様であろう。
つまりこれらは0で初期化される。

290 ◆rCEzuNnL0g:2008/09/07(日) 14:30:37
int *p1 = new int, *p2 = new int();
とすると
*p1は不定*p2は0である。
括弧を付けるか付けないかで此れだけ違います。

291 ◆rCEzuNnL0g:2008/09/07(日) 14:34:53
こんな風にするとウマー?
----
#include <iostream>
#include <string>

struct POINT{
int x, y;
POINT()
: x(), y()
{}
friend
std::ostream &operator<<(std::ostream &, POINT &);
};

std::ostream &operator<<(std::ostream &os, POINT &p){
return os << p.x << "," << p.y;
}

int main(int argc, char **argv){
std::cout << POINT() << std::endl;
}

292 ◆rCEzuNnL0g:2008/09/07(日) 14:37:04
中身が分からない関数の呼び出しは最適化のしようがない。
何故ならば内部で副作用があるかもしれないからである。
staticな変数があってそれが変更されて、後からの動作に影響が出るかもしれないからである。
という事で、関数の呼び出しの最適化はあまり期待しないほうがいいかもしれない。
まあ、全部そのプロジェクトから分かる範囲の関数ならばインライン化してくれるかもしれない。
JITコンパイラ的な奴を自分で組み込むのもありかもしれない。

293 ◆rCEzuNnL0g:2008/09/07(日) 14:40:19
JITコンパイラ的な奴を組み込むとなると、多分初期化に時間がかかる。
やるならば逆アセンブリして解析して、メモリ確保してコピーして埋め込んで、コピーして、
絶対アドレスがあったら修正して云々しなければならないと思う。
まあ、それをやったのが、Firefox3.1に搭載予定の、なんかよく分からん名前のやつであろう。

294 ◆rCEzuNnL0g:2008/09/07(日) 14:42:43
結構、その初期化にかかる時間は長いので、
有名ライブラリの奴をコンパイルしておけばいいと思う。
で、CRCで同じハッシュの奴はコンパイルした奴を使うと。
まあ、こういうのにGoogleが出てくるといいね。
全てのライブラリ使用者がGoogleとかからダイレクトにjQueryとかを利用すれば、
URLを見ただけで態々ダウンロードしてCRCを確かめなくてもキャッシュを利用することが出来る。
まあ、少しぐらいしか早くならない気もするけれども。

295 ◆rCEzuNnL0g:2008/09/07(日) 17:15:42
うーん
三度目ぐらいにC++0xのWikipediaの解説を読んだのだが、複雑すぎで今の僕には理解できません><

296 ◆rCEzuNnL0g:2008/09/07(日) 17:42:11
取り敢えずラムダ関数が使えるようになれば良いねえと。
[](int x, int y){return x + y}
とかうまー

297 ◆rCEzuNnL0g:2008/09/08(月) 18:59:31
プラグイン3種アップデート+SuperView を活用できる便利なスクリプトの紹介 (フェンリル | デベロッパーズブログ)
http://www.fenrir.co.jp/blog/2008/09/superview.html
---
>この FaviconCleaner プラグインは NTFS のアクセス日時を取得する API を使用している関係で Unicode 版のみの配布であり、NTFS 上にキャッシュが保存されている環境に対応します。NTFS ではない場合には何も起こりません。
------
うーん。自分はFAT32上にSleipnirを構築しているので困るなあ。
アクセス日時だったら、FATでもあるんだぜ?
Wikipediaによると
>作成(精度は10ミリ秒), 修正(精度は2秒), アクセス(精度は1日)
>(長いファイル名がサポートされている時のみ、作成時間とアクセス日付が更新できる)
と書かれている。
別に一日という精度だったら問題ないと思うんだけれどもねえ。
ちょっと頑張ってほしい。

298 ◆rCEzuNnL0g:2008/09/08(月) 19:02:37
因みにNTFSだと100ナノ秒単位で記録できるらしい。

299 ◆rCEzuNnL0g:2008/09/08(月) 19:23:59
“Hatena Bookmarker 1.1.3”の修正点について。
>タブ上でホイール回転をおこなうと常時通信が走っていた問題を修正した。(t.o)
確かに直ってますね。多分実装としては、
「選択が変わった or ページが移動した時」にスレッド生成!だけれども動かさない。
また「選択が変わった or ページが移動した時」に前のスレッドがあったらそれを殺す。
で、またスレッド生成をする。
暫く待ったら通信して結果を表示!

という感じだと思う。だから普通に変えただけでは通信までに時間がかかる。
だからキャッシュを利用すれば良いものを・・・。駄目な理由があるんですかね。
Delphiは良く分からんけれども、C++ならばstd::vector<int>とかで簡単に出来そうなんだけれども。

300 ◆rCEzuNnL0g:2008/09/08(月) 19:29:33
Black Hat Japan 2008:ブラックハットジャパン2008
http://www.blackhat.com/html/bh-japan-08/bh-jp-08-main.html
----
こんなのがあるんだ。
到底俺のいけるレベルではない。

301 ◆rCEzuNnL0g:2008/09/08(月) 20:23:52
>>299
どうやら違うっぽい。
という事で、嘘です。
まあ、通信までに時間がかかるのは本当だけれども。


新着レスの表示


名前: E-mail(省略可)

※書き込む際の注意事項はこちら

※画像アップローダーはこちら

(画像を表示できるのは「画像リンクのサムネイル表示」がオンの掲示板に限ります)

掲示板管理者へ連絡 無料レンタル掲示板