【初心者歓迎】C/C++室 Ver.103【環境依存OK】
■ このスレッドは過去ログ倉庫に格納されています
エスケープシーケンスやWin32APIなどの環境依存なものもOK
そのような質問は必ず環境を書きましょう
半角空白やタブでのインデントはスレに貼ると無くなります
コードを貼れる所
http://codepad.org/
https://ideone.com/
前スレ
【初心者歓迎】C/C++室 Ver.102【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1509780815/ そして、charの配列要素が
1つの文字を表してるとは当然限らない
MBCのように連続する複数の配列の要素が
1つの文字を表すことが多い
で、strlen()で文字の数が返却されないのは当然 >>360
曜日の出力もこれで簡単になる
int wday = 4;
printf("%c", "SMTWTFS"[wday]); >>364
それだと土曜日と日曜日の区別がつかないw そいつをlongのポインタにする知恵があれば誉めてあげるんだが int wday=5;
char week[] = "SunMonTueWedThuFriSat";
printf("%.3s",&week[wday*3]);
これでどうだw 悪い例 (キャストの悪用、データサイズの勝手な仮定)
int wday = 5;
printf("%.4s\n", &((int*)"Sun.Mon.Tue.Wed.Thu.Fri.Sat.")[wday]);
軽いジョークのつもりで書いてみたけど、セグメンテーション・フォールトが出て
動くまでに予想外に手間取ってしもうた。
原因はアドレス演算子 & の付け忘れだった。 それを.3sで表示すれば371と同じ結果にならなかね? 表示幅の指定で .3 なら >>371 と同じになるよ。
英単語の省略形にピリオドをつけたいのは好みの問題なの。
今は曜日も月名もピリオドを付けないのが一般的なのかな。
<time.h> の asctime() も3文字3文字だね。 たびたび失礼、そしてまるっきり実用の役に立たない話ですまぬ。
&((int*)"Sun.Mon.Tue.Wed.Thu.Fri.Sat.")[wday]
「いったん[]で配列形式でアクセスしてから要素のアドレスを得る」
なんて回り道をしないでも
(int*)"Sun.Mon.Tue.Wed.Thu.Fri.Sat." + wday
と素直にポインタの足し算だけでいけたね。
…難解Cプログラムに凝る人の気持ちがちょっと分かった気がする。 intのサイズがcharのサイズの4倍でないと動かない
難解ではなくただの知恵遅れのコード sizeofがイマイチ分からないです
型や変数のサイズを出す演算子ってのは分かったんですが
例えばこの例↓どういう風に化けてるんですか?
https://ideone.com/szVAAP
sizeof studentで要素数3だから3に化けると思うんですが、右の*studentは何に化けてるんですか? sizeof が返すサイズってのはバイト数だというのがよくわかってないのかな。
もう C++ では type_traits の std::extent を使って欲しい気持ち。 >>378
分かってないです
ロベールの入門書読んでるんですが説明が少なすぎてこの27行目の式が分かりません。
構造型のバイト数も分かりませんし…int3個とchar一個だから13バイト?
>>379
すいません、分かりません
sizeof(student) / sizeof(Student);が何に化けてるのか検討も付きません
ありがとうございます。 https://ideone.com/aPMXLA
コレでなにが分からないか自分で説明できないなら
すべてを諦めたほうがいい >>380
int のサイズは処理系依存なので、具体的に何バイトとは言えない。
でもまあ現代的なパソコンなら 4 バイトのことがほとんどだろうね。
さらに言えば仕様上は構造体の要素の間にスキマがあいててもかまわない。
> int3個とchar一個だから13バイト?
この構造体中の char は MAX_NAME+1 個じゃん。
まあそれはそれとして、
sizeof student というのは、 student という配列の大きさを「バイト数で」返してきて、
sizeof *student というのは student 配列の要素ひとつの大きさをバイト数で返してくる。
つまり、配列全体の大きさを配列の要素の大きさで割ったら配列に含まれる要素の個数になる。
この場合は 3 ってこと。
sizeof *student が配列の要素ひとつを表現しているっていうのがちょっと分かり難いかなぁ。 >>377, >>380
前にも質問してた人だな
まず、sizeofはメモリ上に確保された対象のバイト単位のサイズを返す(charは1バイト、intは4バイト)
sizeof studentは、配列全体(要素数 x Student型のサイズ)のバイト単位のサイズを返す、配列の要素数は返さない
sizeof *studentは、Student型のバイト単位のサイズを返す
それらの割り算をしてるのだから、結果は要素数になる >>382
>sizeof *student が配列の要素ひとつを表現しているっていうのがちょっと分かり難いかなぁ。
個人的にそういう表記は嫌だわw
変数のサイズを求めるなら、その型名でって思う >>384
へー、私は逆に型名よりも変数名で書きたい派。
これは変数 student について調べたいのであって、
型 Student について調べたいわけでは無いので。 >>382
すいません、おかげさまでどういう計算してるのか理解できました
確かにポインタにすると何で要素一つのサイズなのか理屈づけて説明できません…sizeof student/sizeof student[0]とかだと分かりやすいです
ありがとうございます。意味が理解できたので応用して使えそうです >>384-385
私が sizeof *student が分かり難いと述べたのは
配列名に * を付けたものが配列の先頭要素になるルールの背景にある暗黙の型変換が分かり難いって話。
C/C++ を使ってると空気みたいにやっちゃうんだけど、これ実際のところだいぶんアレなルールですよ。 >>385
型が表すサイズの定数だから、変数から取得するってのが気持ち悪いよ
sizeofなんて何か細かいことワチャワチャしたい時に型のサイズ欲しいよねーって感じの演算子だものw >>388
この場合くらいの小さなサンプルだとあまり気にならないけど、
その変数が何の型であるか知っていなければならないっていうのが、
読むときの負荷が高いと感じてしまう。
自分を信用してないというか、自分がアホだということを信用しているので、
色々忘れて読んでも良いように書きたいと思ってる。 C++ ではもうそんな古代のイディオムなんて忘れて std::extent を使いたい もう C++17 の時代なんだから std::size の方がいいな そもそも
for (int i = 0; i < size; ++i) {
Show(student[i]);
}
のところはモダンな C++ では (つまり C++11 以降では)
for (auto& e: student) Show(e);
と書けるので配列の要素数を事前に計算する必要なかったわ。 >>380
>>382
>sizeof *student が配列の要素ひとつを表現しているっていうのがちょっと分かり難いかなぁ。
私は、これはかなり紛らわしいとおもっているので、こういうときには必ず
struct FOO { int n; ..... } array[N];
int n = sizeof(array) / sizeof(array[0]);
としています、こっちの方が好きです
構造体の配列の第一番目を指すポインタ
struct FOO *p;
p = &array[0];
のときに *p は array[0] に入っている「構造体の一つの要素全体」を表します、すなわち *p イコール array[0]
しかし、この表現はすぐに直感的にイメージとして頭に入ってくるわけではなく、何度となく書いたり読んだりしてゆっくり染みこんでくるものだ、と私は経験しています
同様に p->n とか、これと等価な (*p).n とかの表現など
書き続ければ、あるいは読み続ければ、そういうのは、だんだんわかってくるのではないかな、と。 C を使ってるときは感覚的に理解してて全く不都合なかったけど、
C++ のテンプレートやなんやかやを利用するようになると、
やっぱりちゃんとルールを把握せないかんなと思った。 _countof()
環境考えなくていい(趣味etc)ならこれもある >>388
何かの都合でその変数の型を変えた時に変更し忘れたらバグになる元
型で書く奴はアホだと言い切ってもいいレベル c#から使うクラスライブラリをc++/cliで作っています。
クラス変数をoutで渡してメソッド内で値を入れたいのですが、c++側はどんな風に書けばよいでしょうか? >>401
ありがとうございました。
解決しました。 ロベール入門の内部リンケージ外部リンケージ云々の下りがちょっとよくわからないんですが
externを付けると別のcppの変数を弄れるってことであってますか? externをつけると別のファイルのグローバル変数、関数を使えてローカル変数は使えないんですか? >>403
はい、そうです。
>>404
staticではないローカル変数は外側から参照できない。static付きの変数は静的に確保されるので、アドレスを使えば参照できる。externを付けるのはグローバル変数の宣言。 関数プロトタイプにexternを付けるのは無意味。 >>405
分かりました。
ありがとうございます
staticを付けると内部リンケージになって別のcppから使えない云々書いてありますが
アドレスを使えば弄れるんですか。よく分かりませんね(@@; static int a = 0;
...
f(&a);
もしくは、
int& g(void)
{
static int a = 3;
return a;
}
みたいな感じで。 >>407
リンクってのはシンボル(名前)とアドレスを付き合わせるってこと
プログラマが意識してアドレスを使うなら何でもあり そして次のページにて
ヘッダファイルに#ifndef#define#endifを定義すると2重定義防止ができると説明があるのですが
これを使えばexternとか関数プロトタイプを使わないで住むということでしょうか。
だとするんであればexternとかプロトタイプ宣言とはどう使い分ければいいんでしょうか; 現在利用出来る無償のメモリリーク解析ツールってありますか?プログラム初心者でメモリリークの対策がよくわからないのでどういうところに対策する必要があるのかを知るのに利用したいです vs使えばexpressエディションでも標準装備されてる >>413>>414
ありがとうございます
すみません。言語はCなんですが、スマートポインタなるものは使えるのでしょうか
VSのほう先ずは試してみます とりあえずこんな感じのコードで軽くお試しできる
デバッグモードで実行するとデバッグコンソールにリークしてるログが出力される
コメントはずしてfree()で解放するとリークしてるログがなくなる
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
void aho(void) {
void* p = malloc(100);
// free(p);
}
int main(void) {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
aho();
return 0;
}
↓詳細はココみなさい
https://msdn.microsoft.com/ja-jp/library/x98tx3cf.aspx
あとはもうできるハズだ 入門の+operator演算子で訳わからず詰んでしまったのですが
簡単に分かりやすく解説してるサイトないですか? >>416>>417
ありがとうございます
頑張ってみます! >>420
ありがとうございます
ひとまず扱えるようにはなりましたm(__)m >>418
visual (studioで使える) leak detectorかな?
重いけどスタックトレースがでるので便利。 http://codepad.org/gwutTCie
AIUEOを何回も呼び出したいとき、引数のa, b, c, d, eの部分が共通なので
何回もa, b, c, d, eと書かなくても良いようにしようと色々試しましたが中々上手く行きません
別にコピペすればいいのでそんなに気にすることでもないと思うのですが、
こんなときはどのように書いたら良いのでしょうか? >>424
意図を把握できてるか自信はないが↓のbinded_AIUEOみたいなことでいいのん?
void MACRO(int a, int b, int c, int d, int e, int s, int t) {
auto binded_AIUEO = [=](int x, int y, int z){ AIUEO(a, b, c, d, e, x, y, z); };
if (s < 0) {
if (t < 0) binded_AIUEO(-1, -2, -3);
else binded_AIUEO(3, 0, 7);
}
else {
if (s < t) binded_AIUEO(4, 99, 8);
else binded_AIUEO(333, 33, 3);
}
} >>424
struct Args { int a,b,c,d,e;};を引数に使う void foo(int argc, const char *argv[])
{
}
int main(int argc, char *argv[])
{
foo(argc, argv);
return 0;
}
VC++2008でコンパイルすると、
「error C2664: 'foo' : 2 番目の引数を 'char *[]' から 'const char *{}' に変換できません。」
ってなるんだけどなんで?
constから非constならわかるんだけど。 type ミスなのかコピペなのか判断に迷うとこだけど
'char *[]' から 'const char *{}' 後者が { } になってるあたりにヒントは無い? >>431
2010ではエラーにならなかったな
2008固有の問題なのかも知れない
foo(argc, (const char **)argv);
こうしてみたらどうだろう >>425 >>426 >>427
ありがとうございます
これのマクロ版を書くときはどのようにすれば良いのかと思いました
例えば #define BINDED_AIUEO(x, y, z) AIUEO(a, b, c, d, e, x, y, z)
とすると1, 2, 3, 4, 5ではなくa, b, c, d, eとそのままの文字で展開されてしまいます >>433
こんな感じかな?
#define MACRO(a, b, c, d, e, s, t) {\
#define BINDED_AIUEO(x, y, z) AIUEO(a, b, c, d, e, x, y, z) \
if (s < 0) {\
if (t < 0) BINDED_AIUEO(-1, -2, -3) \
else BINDED_AIUEO(3, 0, 7) \
}\
else {\
if (s < t) BINDED_AIUEO(4, 99, 8) \
else BINDED_AIUEO(333, 33, 3) \
}\
#undef BINDED_AIUEO \
}
この事例ではどうしてもマクロじゃなければ駄目という理由はなさそうだけど、
実際の利用シーンでは何か意味があるのかな? >>434
それできたっけ?と思って試してみたらエラーになった
マクロの中では#は識別子の文字列化になる
可変長マクロを悪用してこんな感じにはできるけれども……おすすめはできない
#define packed_MACRO(s, t, ...) {\
if (s < 0) {\
if (t < 0) AIUEO(__VA_ARGS__, -1, -2, -3) \
else AIUEO(__VA_ARGS__, 3, 0, 7) \
}\
else {\
if (s < t) AIUEO(__VA_ARGS__, 4, 99, 8) \
else AIUEO(__VA_ARGS__, 333, 33, 3) \
}\
}
#define MACRO(a, b, c, d, e, s, t) {\
packed_MACRO(s, t, a, b, c, d, e) \
} >>435
あっ、そうか、間違えた。
ちゃんと試さないと駄目だな。 いずれにしても、マクロでやるのはおすすめできないパターンには違いない。
関数でやってもインライン化されたら定数畳み込みとのコンボで実行コードはだいたい同じような感じになるだろうし。 >>434 >>435 >>437
ありがとうございます
素直にそのままa,b,c,d,eと書こうと思います
この例じゃない実際のコードは、速度を重視した結果マクロを使用することになったのですが、
冷静に考えてみれば計算数回ぐらいしか変わらないのでそこまでやる必要は無かったかもしれません MSVC2017+Windows10でレジストリを読み取ろうとしています。
RegEnumValueW(hKey, 0, name, &nameSize, 0, &type, value, &valueSize)
を実行してtypeがREG_SZのレジストリ入力を読み取ることには成功したのですが、
value先頭のvalueSizeバイトのユニコード文字列をstd::stringに変換する方法が
わからなくて困っています。
具体的にはwindowsのフォント名を読み取っていて、"arial.ttf"に対して
valueの中身を見ていくと、a\0r\0i\0…となっています。
LPBYTEからstringなのでとりあえずwchar_t*にしてからstringにすればよいのかと思ったのですが、
MultiByteToWideChar(CP_THREAD_ACP, 0, (LPCCH)value, (int)(valueSize), NULL, 0));
でサイズ取得してから
MultiByteToWideChar(CP_THREAD_ACP, 0, (LPCCH)value, valueSize, buff, size);
しても要素がchar→wchar_tに変わっただけで、\0も1文字になってしまいます。
できれば日本語にも対応したいので、下位ビットだけ読む、みたいな方法以外の対応を
探しています。ご存知の方いらっしゃらないでしょうか。 >>439
方向が逆。WideChar から MultiByteだ。 >> 440
WideCharToMultiByteでできました!
MSDNでunicode文字列を返すと書いてあったのでUTF16LEかと誤解していました。
ありがとうございました。
書き込むかわからないですが、今後は蟻様と呼ばせていただきます。 > UTF16LEかと誤解していました
いやそこは間違ってないと思うよ
wchar_t* -> utf-16 (winに限る)
string -> 8859-1, utf-8, 等 Win32の用語ではUTF-16はWide Char String. 16bitに収まりきらない場合があるけど、可変長マルチバイトとは呼ばないかな 趣味の自作ゲームでC++を利用しています(多人数開発などは今後も予定なしで、人様のコードは読まない)
Cの「関数へのポインタ」ってC++のポリモーフィズムがあれば理解しなくてもなんとかなりますか?
関数へのポインタが手持ちの書籍だけではわからずにいるのですが、
柴田さんのポインタ本とか買ってまで理解する価値はあるでしょうか?
関数へのポインタの存在理由もわからずにいるので、頓珍漢な事を言っていたらすみません C++のポリホーリズムの運用が完璧であれば問題ない
が、関数ポインタがその理解の助けになるかもしれない ポリモーフィズム
(基底から派生させた各ザコキャラ(各々別クラス)のインスタンスを同じコンテナに入れて各々のメンバ関数(アクションなど)を実行する)
といったかんじで便利に運用できている(と思う)ので、
関数ポインタは理解しなくても大丈夫そうでしょうか
動的関数実行の他にはどんな用途に利用するものですか? >>インスタンス
インスタンスではなくインスタンスへのポインタの間違いでした >>447
抽象クラスを活用してるってこと?
それが上手くいっているならほとんどの場合はその方が良いと思う。
ただ、仮想関数ってのは (言語仕様で決まりがあるわけではないが、一般的なコンパイラでは)
オブジェクトが暗黙に仮想関数テーブルへのポインタを持つことで実現されていて、
仮想関数テーブルには関数ポインタが格納されている。
つまり、仮想関数は関数ポインタを辿る処理を自動化したものなので、
メカニズムをよりよく理解したいなら関数ポインタのことも知っておくとわかりやすくなるかもしれない。
仮想関数テーブルの説明は Wikipedia に簡単なものがある。
https://ja.wikipedia.org/wiki/%E4%BB%AE%E6%83%B3%E9%96%A2%E6%95%B0%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB >>仮想関数テーブルには関数ポインタが格納されている。
>>仮想関数は関数ポインタを辿る処理を自動化したものなので、
やはり関数ポインタが使われていたのですか
Cプログラム診断室のホームページを公開されてる藤原博文さんが
関数へのポインタの利用用途がスラスラと言えるレベルで中級
と書かれていたので、初心者から脱したければ勉強すべきかもしれませんね
普通のポインタでも時々間違える事あるし、ポインタ本は買っておこうかな。
お答え頂きありがとうございました! VC++6.0で作っています。 MFCです。
普通にSDIを作りますが、そこからメニューバー等からダイアログボックスをモードレスで起動します。
すると、ダイアログを起動しながらメインウインドウも触れるようになるのですが、そのフォーカスを
モードレスダイアログとメインウインドウとをマウスを使わずにキーボードで切り替えることって出来ませんか
MSのWindowsOSのAlt+Tabではこれらはひとつとして認識されているようでこれでは切り替えられません
ちなみに、Windows7です 関数ポインタの使い道って…qsort() にて比較関数を指定するくらいしか思い浮かばないのですが…
他の関数に(キャストしまくった)関数ポインタを渡すことはあっても、自分で関数ポインタをコールする (*f)() のはあまりないのです… 関数に関数を渡す関数型っぽいのとオブジェクト指向は根柢から違うんじゃないか? #include <stdio.h>
typedef struct tag_baka_t t_baka_t;
typedef int (*baka_func_t)(t_baka_t const* pt_baka);
typedef struct tag_baka_t {
char* text;
baka_func_t function;
} t_baka_t;
int call_baka1(t_baka_t const* ct_baka) { fprintf(stdout, "baka1:%s\n", ct_baka->text); return 1; }
int call_baka2(t_baka_t const* ct_baka) { fprintf(stdout, "baka2:%s\n", ct_baka->text); return 2; }
int call_baka3(t_baka_t const* ct_baka) { fprintf(stdout, "baka3:%s\n", ct_baka->text); return 3; }
int call(t_baka_t const* ct_baka) {
return ct_baka->function(ct_baka);
}
int main(int argc, char* argv[]) {
t_baka_t baka1 = { "boo", call_baka1 };
t_baka_t baka2 = { "foo", call_baka2 };
t_baka_t baka3 = { "woo", call_baka3 };
fprintf(stdout, "called baka1 -> returned %d\n", call(&baka1));
fprintf(stdout, "called baka2 -> returned %d\n", call(&baka2));
fprintf(stdout, "called baka3 -> returned %d\n", call(&baka3));
return 0;
}
C言語の構造体ならコレでいける
コレならバカでもチョンでも分かる
C++の構造体でも同じように書ける >◆QZaw55cn4c
いつまで荒らし行為を続ける気だ >>454
スクリプト言語の拡張を C で書いたりすると、関数ポインタを使うこともまあまあある。
言語に限らずプラグイン的なものだと関数ポインタのやりとりは結構あるんじゃない?
Regnessem のプラグインを作ったことが有るが、プラグイン側の関数を本体に登録したりする
処理に関数ポインタは使ったぞ。
それはそうと、関係ないけど Lisp Scheme スレに書いてた疑問は解消できたの? >>458
> Lisp Scheme スレに書いてた疑問は解消できたの?
身辺が忙しくなってしましました、暇をみつけてじっくり考えています(ちょっと最初の方に戻っています) >>458
window classを登録するときとか普通に使わない? qsort のような、問題先送り系コールバック関数は関数のポインタになっちゃうわね >>458
regnessem懐かしい
どのプラグイン作ったの? ■ このスレッドは過去ログ倉庫に格納されています