【初心者歓迎】C/C++室 Ver.103【環境依存OK】
レス数が1000を超えています。これ以上書き込みはできません。
tupleの要素取り出すときstd::get<>以外の方法ありますか?
tuple[index]みたいに取り出せたら良いんですけど テンプレート特殊化を使えば出来るけど、そういうのは汚いコードだね。 >>515
tuple の要素が char * だとして
std::vector<char *> vec;
int i = 0;
std::_For_each_tuple_element(t, [&h, &i](auto&& v){
printf("%d: %s\n", i++, v);
vec.push_back(v);
}); >>519
求めていたのはこれでした
ありがとうございます すごく初級の質問なんですが、
int * x =3;
auto y=*x;
としたときに、コンパイラがyの型をintと推測するのはなぜでしょうか?
ポインタのポインタになるので、最初の*でint型の変数のアドレスを示すことになるまでは分かるのですが、
その後の*でアドレスのアドレス?を指すことになるので、元のint型の値を指すのは違うように思えてしまいます。 x は 0x00000003をアドレスとして認識
y(*x) は int型アドレス0x00000003にある値を指す
アドレス(x)のアドレスを指す場合は &x になる 多分、変数yの型が省略されているから、
デフォルトのintと推定して処理しているのだろう >>522
ありがとうございます。
ということは*がついてる変数は、変数がアドレスのときはそのアドレスに収納されてる値を指し、変数がアドレスに収納されてる値のときは、そのアドレスを指すという理解でよろしいんでしょうか? >>525
違うよ。
型名の一部としての*と、式の中の演算子としての*が別物だと言うのは分かる?
1行目の方は「intをさすポインタ」という型を表すためのもの。
2行目は「xというint型の変数の値に対して、その値が指しているメモリ領域上にあるint型の値を参照する」という演算を行うというもの。 この変数はポインタです 宣言の *
ポインタで指している先の内容を得ます 式の * C++コードの部分を間違って読み込んだとか?
エンコードはEUC-JPだね Firefox だと右上メニューからエンコーディングで明示的に EUC-JP 指示で化け解消
(unicode にチェックが入ってたが、自動だとそっちに誤爆判別してた?)
Chrome での明示的なエンコーディング変更は拡張プラグインつっこまないとできないっぽい C/C++ のポインタの表現が分かり難いってのは確かにあると思う。
宣言のときも * は変数名の側にくっついているものと考えれば理解しやすいんじゃないかな。
int * x; と宣言したとき、 *x が int であるような x を宣言したことになる。 Cの頃は
int *hoge;
と書くことが多かったのに、
C++になってから
int* hoge;
と書く人が増えた。
悪い習慣だと思う。 Javaとかから入る人が増えたからかね?
その習慣はあかん。
ポインタは型じゃないから、例えば
int* a,b;
って書くとaは「int型のポインタ」で、bは「int型の変数」になる。 >>532
いや、そこらへんは C/C++ のおかしなところで、ポインタはあくまでも型だ。
その上で文法上は * は変数名の側と結合するの。
もういっそ
std::add_pointer<int> a, b;
のスタイルを普及させればいいんじゃないのかなーと思う。
C++ だとなるべくスマートポインタを使う習慣が出来つつあるから、
その記法とも一貫性があるし。 >>532
ポインタは型じゃないって言ったとき
じゃあなんて言うんだっけ
仕様でも厳密にはなんか型とは別のカテゴリとして扱われてたよな
仕様に詳しい人教えて 型変換は (型)式 と書くわけで型を単体で書く書き方はあるのに変数宣言は
型 変数[, 変数]...
じゃないからねえ
void f(void);
void (*f_ptr)(void) = f; // ふむ
void (*g_ptr)(void) = (void(*)(void)) f; // 関数ポインタ型の記法はこうか…
void (*)(void) h_ptr = f; // 型 変数で書いてみた→エラーかい!
みたいな 初期化リストで二次元配列を0で初期化したいときはどう表記したら良いですか? 初期値式リストの個数が足りない場合残りの要素は0で初期化されるので
int a[5][6] = {};
でok >>538
CやC++では、ゼロクリアされるのか。されないと思っていたが 初期化値リストをつければ足りないところは0で埋められる
付けなければ初期化されない
太古から変わらない仕様 あ、でも c だと空の初期化リストは書けないから {} じゃなく {0} にしなきゃダメか >>535
変数宣言の基本的な形式
型指定子 宣言子1, 宣言子2, …;
で言うと * は宣言子の一部ということになるが、
型指定子でないから型 (の一部) ではないというわけではない。
これは文法上の呼び名に過ぎず、
意味論的にはポインタは型の一部だよ。 視点の問題ではあるが宣言の構文上のポインタは型の種類ではなく入れ物の種類ともいえる
int *a, b;
は
int pointer a, int variable b;
を意味する省略構文であり意味論的に
variable:値をいれるもの
pointer:間接的に他の入れ物を指すもの
と区別されてると見ることもできる >>544
そういうのは単純なポインタ(foo*)の時にだけ通じる話で、配列や関数ポインタや引数込みでのそれらの再帰的な組み合わせとかも考えたら、きちんとBNFで理解して型の宣言の構文を定義通りに覚えるのが一番誤解がなくてシンプルだと思うよ。 >>543レスサンクス
自分でも調べてみた
手元のc99ドラフト版から適当に抜粋
declaration:
declaration-specifiers init-declarator-list ;
declaration-specifiers:
storage-class-specifier declaration-specifiers
type-specifier declaration-specifiers
type-qualifier declaration-specifiers
function-specifier declaration-specifiers
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
declarator:
pointer direct-declarator
pointer:
* type-qualifier-list
* type-qualifier-list pointer
宣言時の * は declarator なんやね構文としては >>535
詳しい人とかハードル上げられるとな。。。
プログラミング言語C売っちゃったから、厳密な仕様は記憶の彼方だが、ポインタは厳密なカテゴリ的にもポインタだったと思う。
ここからは私の解釈だが、ポインタはアドレスを入れる「変数」。
当たり前じゃんと言われればそうなんだけど、感覚的にも型というより変数って感じ。
ポインタに型があるとすればOSがアドレスを扱うビット数と同じになる。
intとかの型はポインタが指す先にどの大きさのどういう扱いのデータがあるかを知る為で、ポインタ型そのものの大きさは変わらない。
んで、普通の変数とポインタはCだと大分違うように思うけど、アセンブリ言語だと
LD GR0,TEXT ; 変数TEXTの内容を読む。
LDA GR0,TEXT ; 変数TEXTのアドレスを読む。
程度の違いしか無いわけね。
この場合、内容もアドレスもレジスタが読むけど、Cにレジスタに相当する変数を用意する為にポインタが生まれたんだと思う。 >>547
私の解釈? ポインタが生まれた理由?
なんでその内容を俺にレスしたのか意味不明 x Cにレジスタに
o CにLDA使用時のレジスタに carとcdrに付いて小一時間
こちらの方が先だべ >>538
ありがとうございます説明が足りなかったかもしれません
メンバ変数の配列をコンストラクタでリスト初期化する場合どうしたらいいですか?
Hoge::Hoge() : mPiyo(0) ←これの二次元配列版を知りたいのです >>551
同じだよ {} で初期化すればいい。
Hoge::Hoge() : mPiyo{} {
ほにゃらら
}
ってことね。 >>547
言語実装ベースの思い込みが過ぎる。
言語規格中のポインタは型だし、変数ではない値もあり得るし、ポインタの指す先の型の違いは大きさだけではない。
↓「ポインタ型」で検索して確認されたし。
http://kikakurui.com/x3/X3010-2003-01.html > void (*)(void) h_ptr = f; // 型 変数で書いてみた→エラーかい!
当然知ってると思うけど
void (*h_ptr)(void) = f;
これは * と () の優先順位が原因だ
よく * と [] で混乱してるひともいるけど
char **hoge;
char *hoge[];
char (*hoge)[123]:
char (*hoge)[]: // エラーかい! >>551
今では (C++11 以降では) 宣言時に初期化も書けるから、
struct Hoge {
int a[10][10] = {};
public:
Hoge(void);
};
って感じでも書ける。
複数のコンストラクタがあるときに、
どのコンストラクタが起動したときでも初期化はしないといけないみたいなときには、
この方式で書いた方が何度も同じことを書かなくてよいので面倒くさくなくて良いかも。 >>556
なるほど
コンストラクタにつらつら書くよりもヘッダで宣言時に初期化した方が綺麗ですね アセンブラとかから C に入門したら色々と自動化されてて
ありがたいなーってなってポインタで躓いたりしづらいけど、
レイヤが違うという意識を持ってないと変に機械の理屈に引きずられることもある。
言語の理屈だとポインタはアドレスを入れるものじゃなくて、
ポインタを値として見たものをアドレスと呼んだりもするってだけ。
結局はポインタにアドレスが入ってるんだけど、まずポインタありき。
ポインタに対する演算ってのは指す先をいくつ進めるとか、
指す先の間隔がいくつだというものであって、
アドレスを演算して実現するってのは実装上の都合。
アドレスが連続しているということさえ保証はない。
たとえば
char a[2];
とあったときに
(intptr_t)(&a[1])-(intptr_t)(&a[0])
が 1 になることは言語仕様では保証されない。
(これが 1 にならないような変な環境はまず無いと思うんだけど。)
具体的に機械でどう動いているかから見ると肌感覚として理解しやすい場合もあるのはわかるが、
言語の理屈と混同しないように、一旦それは抽象の壁の向こうに押しやる必要もある。 ラムダ式でthisを指定してそのクラスのメソッドを呼び出したところ、そのクラスのメンバ変数がすべて0になっててコンストラクタも動作してない状態になってたのですが、使い方間違ってますか >>559
インスタンスが既に破棄されているのでしょう
c++ ではオブジェクトの寿命管理は自分でやる必要があります
(参照があるから破棄されないということはない) >>559
[&*this]
こうしたっていう意味? ラムダ式にはthisを指定しました
インスタンスは生きています
ラムダ式内から直接呼ばずにグローバル変数に保持したインスタンス変数経由で同じメソッドにアクセスしたら正しい値が読み取れました auto f = [this]() {... };
てな感じにキャプチャはしてるんだよね。してないとコンパイルエラーになるし。
デバッガでみておかしいだけならデバッガがうまく動いてないだけでは?
cout << this->hoge;
とかして見てみたらどうでしょう。 >>562
>ラムダ式内から直接呼ばずにグローバル変数に保持したインスタンス変数経由で同じメソッドにアクセスしたら
warning読み飛ばしてるだけだと思うが
warningにそうしろって書いてあるはず あとグローバルにしなくても
ラムダ式を呼ぶ側の関数内のローカル変数で保持しても多分いける 複数のファイルをコンパイルするとき、ソースファイルの読み込み順番ってc++ではどのように決定されるのでしょうか? 読込み順番ってのが何を言おうとしているのかよくわからんぞ。 >>566
それぞれ別の翻訳単位として、独立に処理されるぞ。
依存関係があって先に読み込ませる必要があるファイルは、#includeで明示的に指定した順に読み込ませる必要があるよ。 先に読み込ませれば (ヘッダを include したり宣言を書いたりしなくても) 定義したものが利用可能になると思ったってことなのかな? ソースファイルの読み込み=ソースのコンパイルとして
makeなり 統合環境なりが 依存関係チェックして必要と思われた順にコンパイラを起動しコンパイルしてる >>571
>makeなり 統合環境なりが 依存関係チェックして必要と思われた順
別に make による依存度チェックが必須だとは思っていません
最悪、アプリケーションを構成する全ソースを全部コンパイルしたっていい
やっていることがよくわからないのなら、全部再コンパイルするバッチを書いてもいい、と思っています >>572
確かに、時間が無駄になるだけで、それにより動作が変わってしまう等の害を及ぼすことはないからなー
結局 >>566 が聞きたかったことは皆目見当がつかんけどもw vectorで複数のstd::stringの各要素を収納して管理してみたいのですが、
実際、vectorの特定の要素にアクセスしてstringのデータを入れようとするとエラーになってしまいます。
例えば、次のようなコードの場合です。
std::string A = "bookA";
std::string B = "bookB";
std::vector<std::string> booktitle;
booktitle[0] = A;//コンパイルエラー
vectorで複数のstd::stringのデータを収納したい場合にはどうしたらいいのでしょうか? >>574
booktitle.push_back(A); >>573
FreeBSD 2, 3, 4 (くらいかなあ) 時代には、OS カーネルを再度コンパイルすることはあたりまえだったんですけれども、最近はそういう話はすたれてしまいましたね… >>575
ありがとうございます。
例えば、vectorにpush_backで100個のstd::stringのデータを入れたけれど、38個目のデータを別のものに変更したいという場合、
38個目のstd::stringのデータを直接指定して別のものをいれるということはできないんでしょうか? >>577
38個以上格納した後なら、
booktitle[37] = A;
で書き換えられる。 >>577
c の普通の配列みたいに中身に拘らずとりあえずサイズ100の配列を用意したい場合は
v.resize(100) でいけるのでその辺りも併せて覚えておきましょう 関数の中でポインタ変数を作ったら、その関数から出る時、ポインタ変数は消えるけど、ポインタ変数の中身はどっか別にあって消えないってことで良いんですかね?
その中身を消すのがdelete関数ってことですか?ややこしいな・・・ ありがとう。すみませんもう一つ。
ポインタ変数のアドレスを格納するのに、なぜ二重ポインタが必要なのかがいまいちわかりません。
単に”番地”を格納するだけなら普通のポインタでも良いような気がしてしまいます。 それは、32ビット浮動小数点のビットパターンを32ビットintに入れておけば
float型とかいらないと言ってるようなもの アドレス値がほしいとき
引数でアドレス入れる変数のアドレスを渡すことがある >>582
情報量としては実際のところメモリアドレスなので同じだけれど型が違う
pがint へのポインタなら
*p はアドレス位置にある int を返すし、
p++ すると int のサイズ分増えるし、
p[i] はintのサイズかけるiのメモリ位置にある int になる
上記の int を char やポインタ型に入れ替えると動作が異なることがわかる。
なんの型で読み書きするのかとかサイズの計算なんて人がコードで書けばいいじゃん、
という流儀もあるだろうがcは違う
例外としてなんの型だか不明なものを扱うときには、
とりあえずvoid*で保持しておいて計算やアクセスするときに
明示的に型を指定して用いることもある アドレス渡さないと変数(今回の場合アドレスを格納する領域)に値を格納できない
コレはどんな変数でも同じ
アドレスを格納する変数もただの変数だからな >>580
>ポインタ変数の中身はどっか別にあって消えないってことで良いんですかね?
(ポインタ変数の中身はポインタだが、ポインタが指してる先と読み替えよう)
指してる先はどっか別にあってって、言語が自動で作ってくれるわけじゃないよ
ポインタが指す先もプログラマが作らなきゃならない
だから消える所に作れば(自動変数な)消えるし、消えない所に作れば(静的変数やnewな)消えない
>>582
二重ポインタ(って表現もナニだが…)も
ポインタを指してるってだけの普通のポインタだから 「戻り値ではなく、引数の書き換えで呼び出し元に新たな値を渡したい」
・関数側宣言はポインタで受けて 呼び出し側は変数に&つけてポインタを渡す (c/c++)
関数実装の際 *でデリファレンスして代入
・関数側宣言は参照で受けて 呼び出し側は変数をそのまま渡す (c++)
関数実装の際 そのまま代入 >>582
freeしたあと確実にNULL代入したいためにポインタのポインタで管理しておくことはある あと二重ポインタとかダブルポインタとかいう用語は使わない方が良い
ポインタのポインタ(たまにポインタの配列)
配列のポインタ
のどっちかにしろ void my_free(void** ptr) { free(*ptr); *ptr = NULL; }
.......
char *data = malloc(size);
.......
.......
my_free(&data);
/* これ以降 data = NULL になってるから参照するとヌルポになる */ >>590
なんで?
double pointerも十分すぎるくらい市民権得てると思うけど。 >>594
char pointer と double pointer が並んでも? 自分がそう呼ぶかどうかはともかくとして、
ダブルポインタやdouble pointer でググればわかるようにそう呼称されることも大変多いわけだから
ポインタのポインタをダブルポインタと呼ぶことが多いことを知らんでいるわけにはいかんのが現実 **ダブル ***トリプル ****クアドラプル?
うーん 使うのはポインタのポインタまでにしとかないと書いててワケわからなくなるぞ 素朴な疑問だけど、ビット演算の | と論理演算の ||
前者を「オア」と呼んで後者を「ダブルオア」と呼ぶ? >>600
|| は論理演算子の「論理or」
| はビット演算子の「ビット or」…あまりそういういいかたはしないような気もしますが ダブルポインタの流れで気になったのよね
言葉だけの疎通で どう言ってたかな?と
※ 「ビットor」 「or」 後者は前後の文意で汲んでくれ のような使い方してるわ 明示的にビット毎のorを指すときは bitwise or と書くけど日本語ではなんていうんだ
教科書なら「ビット毎の論理和」でいいんだろうけど古臭い
声に出して読むときは2つ組みの方をオアオアとかアンドアンド >>604
世間で使われてる用語を使わず「理屈で言えばこうだ」と
勝手に言葉を作ってると造語症と思われるぞ double linked list のdoubleは行きのポインタ(リンク)と帰りのポインタでdoubleだし
日本語より論理的と言われがちな英語も割といい加減だよね
日本語では双方向リストと実に論理的な呼称 いや double pointer, triple pointer と増やしていけるし数学的なのかな
これ式で日本語でたまに使われるのは2重(2段)ポインタ、3重ポインタか >>603
JIS だと「ビット単位のOR演算子」と「論理OR演算子」と書かれている。
あくまで訳語のひとつでしかないけど、JIS の性格を考えれば公式訳と言ってよかろ。
| と || の代替表記として bitor と or があるので、発音するときはこれでいくのもアリかもね。 二重ポインタを思わず「ハンドル」と言ってしまって怪訝な顔をされる俺。 C99 をざっと見た感じでは double を指すポインタは "pointer to double" という書き方になっているけど、
カジュアルな場面で double pointer と言わないとも言い切れないだろうし、
これについては >>595 の言い分に説得力を感じる。
英語がよくわかる人の肌感覚ではどんなもんなんやろね? ポインタへのポインタでしかないもんを
ダブルポインタと言い換えるの気味悪い だからな
ただの変数だからな
ただのポインタも例外じゃない >>607
doubly linked list じゃね?
https://books.google.com/ngrams/graph?content=double+linked+list%2Cdoubly+linked+list&case_insensitive=on&year_start=1800&year_end=2008&corpus=15&smoothing=3 >>613
お前さんの感覚なんてどうでもいい
pointer to pointer c でググると
Double Pointer (Pointer to Pointer) in C
https://www.geeksforgeeks.org/double-pointer-pointer-pointer-c/
が最初に出て来る現実を見なよ おまえら、本当の0からの初心者にも、やさしくしろよな。 初心者だから何でも許されるというのは間違った考え
安田はジャーナリストとしては初心者
無能に仕事を任せるのは損失 むしろ無能を起用した側の責任も
ジャーナリストは自己だが >>619
そういうお前が一番の初心者じゃねえのかw プログラム全体でただ1つだけ走らせることが出来る、ある機能を提供するライブラリを作りたいんですけど
シングルトンで実装するのが一般的なんですかね よくわからん それただのcの関数やんけ
staticのメンバ関数で十分 スレッドの数なのか変数の数なのか
なんでライブラリがそんなことを強制せにゃならんのか よくわからん状態で作って、システム停止状態になる予感 >>819
そんな考えだったら、スレタイの、【初心者歓迎】をはずせ。 >>819
>絶対許さない
え、どういうことですか? vector<int> v{1, 2, 3, 4};
と定義して &v[0] からのバイト列にアクセスすると
01 00 00 00, 02 00 00 00, 03 00 00 00, 04 00 00 00
と連続して確保されているようですが
●これは仕様上保証されていますか?
また
vector< vector<int> > w{{1, 2}, {3, 4}};
と定義して &w[0][0] からのバイト列にアクセスすると
01 00 00 00, 02 00 00 00, ?? ?? ?? ??, ?? ?? ?? ??
後半がランダム?
になるようですが
連続に
01 00 00 00, 02 00 00 00, 03 00 00 00, 04 00 00 00
と確保されるように2次元のvectorを定義するにはどうすれば出来ますか?
それとも出来ないのでしょうか? >>632
エンディアンもintサイズも固定じゃないので保証されない vector の連続性について
ttp://cranehouse.dojin.com/program/vector.html
ttps://www.wdic.org/w/TECH/std::vector#xE3x83xA1xE3x83xA2xE3x83xAAxE3x83xBCxE3x81xAExE9x80xA3xE7xB6x9AxE6x80xA7 vectorには本体データの他に管理データもあったりするので
そのvectorを作ると間にゴミに見えるデータが入りうる ありがとうございます
int (*hoge)[要素数]; じゃなくて
int *hoge[]; みたいにポインタの配列になってるということでしょうか? w[0] が返す vector の次元(大きさ)と
w[1] が返す vector の次元(大きさ)は異なっててもいい
から、そもそも論で 2次元配列 とは等価にならんし 前者だと要素追加しようとしたらどんちゃん騒ぎだよね >>632 >>640
array< array<int, 2>, 2 > w{ {{1, 2}, {3, 4}} }; 適当なラッパーを作って
期待する形のバイト列にするイテレータをくっつける
とかいった方法が考えられるかなぁ。
まあ場合によるけど、
大きさがコンパイル時に確定してよいのなら、
>>641 の方式が確実だと思う。
多次元配列を作る場合ってほとんどの場合はコンパイル時か
オブジェクト構築時には大きさが決まってると思うんよね。
後から伸ばしたり縮めたりってあんまりしなくなくなくなくない? 1次元での連続性の要求は理解できるけど、2次元以降の多次元で配置の連続性の要求って何処からきてる?
思い浮かぶのが画像データぐらいだけど、それなら1次元+演算でも代用可能だし… 2次元配列状のデータを2次元ベクタに一発で流し込めるからじゃない? 環境に関して質問です。
windows10でcの環境作りたくて、コンパイラにminGWを入れたのですが、実行時エラーがでなくて不便です。
例えば、
char c='x';
printf("c: %s",c);
のように出力時のフォーマットを間違えたら、LinuxではRuntime error〜となにかしらエラーがでていたのに、エラーも何も出ずに(c: すら出ないで)終了します。
minGWの仕様なのか否か。
または、
windows10でminGWを使い、実行時エラーを出す方法を教えてください。 >>645
言語仕様的には未定義なので、実行した結果がどうであっても言語仕様通り。
ランタイムに捕捉できることを期待しない方が良いと思う。
C/C++ っていうのはそういうもんだから。 >>645
minGWを使ったことないんで間違っているかも知れないが
GCCならGDB使えば実行時エラーを捕捉出来るんじゃないか? >>647
gdbで捕捉できるんですが、gcc実行のみでRuntimeErrorを表示させるにはコンパイラ変えるしかないですかね?
もともとvmにLinux入れて、c言語を学ぼうとしてた初心者の集まりなんですが、vm重いからwindowsに移行しようと、環境設定が簡単な方法をいろいろ試してるところです。
なので、Linuxでできてたことができなくなることが不安という感じです。 >>648
例えば、GCCの代わりにVC使ったとしても
エラーを捕捉出来るかどうかは分からないよ
どちらかと言えばOS側の仕様な気がするし たまたまアクセスしたアドレスがアクセス違反でもない限り、そもそもエラーにしようがない気がするのだけど、どうやって補足してるの? 多分リンクするランタイムライブラリ側の仕様ではないかと >>645
エラーレベル上げるとかそう言うフラグがコンパイラに無かったかな?
その初期値が違ってるだけじゃ無いの? あ、実行時か。
Cは実行時エラーの処理も自分で補足して書くものよ?
そう言う言語としか言えない。 不定や未定儀を自らトラップするコードを記述するのは難易度高いな… 例外が捕まれば御の字だが アドレスが 0 付近のページはプログラムミスでアクセスされやすいってことはわかっているので、
Windows でもなんか特別に予約してたような気がしたんだが、手元の資料で見つからんな……。 MMU付きのシステムなら、0番地をTLB missさせるのは一般的だね
けど、これ見るとwin95は違ったみたい。winNTはそうしてたみたい
Why is 0x00400000 the default base address for an executable?
https://blogs.msdn.microsoft.com/oldnewthing/20141003-00/?p=43923 0番地ってNULLポインタ値に割り当ててなかった? >>657
NULL はあくまでも「無効なポインタ」を表し、意味のある番地ではない。
けど、うっかり意味のある番地としてアクセスしたら 0 番地だから、
その付近へのアクセスがあったらたぶん駄目なプログラムとして検出しようねっていう話。 今回の場合は char をポインタとして解釈してしまった場合ってことになるけど、
(0 ではないが) 0 に近いアドレスなので、その付近のページは
トラップ用に予約しておいたらあかんプログラムの検出に便利やんというわけ。 本筋とは関係ないけど念のために補足しておくと、ヌルポインタがゼロというのは、
そういうアーキテクチャがほとんどだと思うけど言語仕様の保証はない。
整数のゼロと互換性はあるという扱いで、
つまりは、ヌルポインタを整数にキャストするとゼロだし、
ゼロをポインタにキャストするとヌルポインタになることは保証されるが、
ヌルポインタのビットパターンが整数のゼロと等しいことは保証されない。
(なので移植性が必要ならポインタの配列を memset とかで初期化したりするのは駄目) >>ゼロをポインタにキャストするとヌルポインタになることは保証されるが
そうだっけ。定数のゼロだけでは? >>661
そういや C++ ではそういう変更もされたような気がするな。
以前は確かに定数に限らずゼロはヌルってことだったはずだが。
C では今でもヌルはゼロ (と相互に変換される) だと思う。 >>661-662
リテラルの 0 じゃなきゃダメなように改められたのは C++14 からだった。 >printf("c: %s",c);
va_list な関数でフォーマットからパラメータの妥当性チェックって
コンパイル時に出来るもんなのか? コンパイル時にprintfのフォーマットチェックくらい出来る >>664
標準ライブラリ関数みたいに、コンパイラ作成時点で仕様が確定してれば可能。
https://wandbox.org/permlink/d1F80sYjt6FhgjY8
> prog.cc:5:19: warning: format specifies type 'char *' but the argument has type 'int' [-Wformat] 逆に言えばコンパイラが特別扱いする必要があるってことだね。 面倒なので出力書式には%sのみを使うこととし引数の型の分だけstringに変換する同名関数用意して必ず文字列にしてしまうという力技 >>669
オブジェクト指向的にはそれが正解なんだよな >>669
まあ結局どこかで文字列化するんだからその考え方もありだね cout << left << hex << showbase << setfill('0') << setw(8) << i << eol;
より
cout << i.tostring("0x%-08x") << eol;
とかなら %書式 にはあまりこだわらないんだけど
前者の仕様だと %書式 の方が描きやすいから
結局普及しない原因 よくint型のサイズとかエンディアンが処理系依存って解説を目にしますが
この「処理系」ってコンパイルするマシンのCPUですか?
それともプログラムを実行するマシンのCPUですか? >>673
コンパイルするプログラムや出来たプログラムを実行するOSやハードウェアなどの諸々の環境 ターゲットになる処理系にあわせてコンパイルするからな
べつにターゲットになる処理系でコンパイルする必要はない ありがとうございます
ちょっとプログラムを見直してみます >>673
CPUで変わるのはもちろんだが
クロスコンパイルも可能なので
コンパイル時のオプションでも変わる constexpr char *mes[] ={(char *)"error", (char *)"ok" ,(char *)"abc"};
みたいにキャストしないとワーニングがでるんだが、めんどくさいね。なんか方法ないの? constexpr const char *mes[] ={"error", "ok" , "abc"};
constexprが何にかかっていたか考えてみれ constつけたらワーニングが無くなるのだろうか? 何故なくなるの?
ポインタにかかるのか、ポインタの中身にかかるのか?という問いだろうけれども恐らくはポインタ自体
にかかるのだろう。そしてconstがポインタの中身にかかる。順番が逆だといろいろ不都合がしょうじる
から、このようになる筈だ。
しかし、constを追加しただけでwarnningが消える理由はなんなのだろうか? (char*)でキャストするのと
同じ効果を持ちうるのはなぜか? constにはそんな意味はない。「単に書き換えできないようにする」
と言う意味だろう。書き換えできないsringももちろんあるから矛盾が生じるのだ。その矛盾を
解決する可能性があるとすれば書き換えできないstringがすなわちchar*と同じである場合に限る。
つまり
const string とは char* の事なのだ。
あってる?
もしあってるとすれば、
constexpr (char*) char *mes[] ={"error", "ok" , "abc"};
でもOKな筈だね。そうでないと矛盾する。この方が分かりやすいね。 そしてワーニングはすべてきえたが、エラーになった。w constexpr const char *mes[] ={"error", "ok" , "abc"};
これをクラスのなかで定義したいのだが、クラスの中で定義するとエラーになる。クラス内だけで使いたいのに
外部に引き出すのは面倒だ。どうしたらいいの? >>681
書いている意味はさっぱりわからんが、文字列リテラルの型は const char[] だ。
そんでもって >>679 の場合の文字列リテラルは暗黙の型変換で const char* になる。
const char* を char* に入れようとしたら型が合わないがキャストで無理やり合わせることも出来るという簡単な話。
だが、型から const を剥がしたからといって文字列リテラルを書き換えてよくなるわけではない。 (← 重要!)
const を剥がすだけなら問題はないが、
書き換えたら駄目 (未定義) にもかかわらず型から const を外すのは馬鹿馬鹿しい間違いの元。
よくわからんままキャストしたら警告が消えた〜〜っていうのはC/C++ の歴史で何十年も繰返してるので
古参ならうんざりするほど見てきた駄目なパターンだと思う。
とりあえずキャストってのはほんとにやめて……。
(ちなみに C では文字列リテラルの型は char[] だが、書き換えるのは未定義ってことになってるという更なる闇がある) >>686
カタカナにする時点で元の発音からずれまくりなので×も△も五十歩百歩だろ。 今調べてきた。確かにwikiとかでもウォーニングってなってんな
発音記号もcの逆みたいのが使われている
でも実際の発音を聞くと、あの方が近いぞ。まあどっちでもええわ 5chで発音ガーとか何回見たことか…
なのでそういう奴が居そうなスレでは原語(warning)で書くのが基本 「文字列リテラル型」って表現はよくわからない。文字列はリテラルじゃないの?
文字列のリテラル型というのであればリテラル型でない文字列ってあるんだろうか?
リテラルって何? 英語をやくしたら文字列って意味だろ。 即値というこれまた訳のわからない訳が出てくるからw A character literal is a type of literal in programming for the representation of a single character's value within the source code of a computer program.
「文字列リテラル」ってキャラクターリテラルのことだろうか?
それなら日本語にすると「文字列」でOKと思う。文字列リテラルって文字列列ってことか?
つまりA character literal literal **str のこと? char a[] = "abcd";
左辺のaが文字列で 右辺の "abcd" が文字列リテラル のんのん \0終端の文字配列 で 文字列になねるー >>703
アッごめん。704は無視して。
リテラルって、堅物って意味のほうか? そうなんだ。 literalって頭が固くて融通が利かないって意味があるみたいだから、”abc”というように値が固定した
文字列って意味なんだね。
ということは
char literal 'a'
char literal "abc"
int literal 0x111
ということか。 まちがってる
char [] literal --> "abc" "literal"って「文字通り」ってことだろう。
ソースコード中に埋め込まれた、値そのものを表す記述のこと。 リテラル型という用語もあるが、リテラル型がいわゆる「リテラル」とは限らないので気を付けてな。 >よくわからんままキャストしたら警告が消えた〜〜っていうのはC/C++ の歴史で何十年も繰返してるので
>古参ならうんざりするほど見てきた駄目なパターンだと思う。
>とりあえずキャストってのはほんとにやめて……。
void uprint( char * message);
こういう関数って普通にあると思うが、そうすると
uprint((char *)"abc");
こんなふうにキャストしないでwarnigを取る方法ってありますの?
そもそも関数の定義の仕方が悪いって意見? C++ってcと混在一体で使うところに多大な
メリットがあるわけで、cだとstringとか使えないし、どうすりゃいいのよ。 あっ、わかった。C++の場合はvoid uprint( const char * message); も作っておけばいいのか。
納得。 >>702
>for the representation of a single character's value
a がついてるだろ。 つまりこれは1文字のことを言ってるんであって、複数文字ではないよ
で、主語を見ると、A character literalってあるから、そもそもこれは1キャラクタのリテラルの定義
なので、複数キャラ、単語等のリテラルの定義は他にあるはず 書き忘れた
a と、わざわざsingle もつけている charactor literalって命名は違和感あるな。
float literal 123.4 だぜ。 おかしいだろ。 float leteral なら"123.4"なら許せる。そもそもliteral使うところが
おかしい。
英語にだってconstantって言葉あるんだから、constantをつかったらいいのに。ところがconstはconstant
のことかと思いきや、read only 変数のことなんだよね。w 何がおかしいのかさっぱり分からん。
"文字通りの"という意味に囚われてるのかもしれないが、ソースコード上に123.4とあったらまぎれもなく文字通りだろう >>713
勘違いしてね?
void f(char * message)
void c_f( const char * message)
のとき、
char *p = "abcde";
f("abc");
c_f("abc");
f(p);
c_f(p);
は全部警告なしで通るぞ。 問題があるのは、
const char *cp = "abcde";
としたときの
f(cp);
だけがエラーあるいは警告になる
2017の最新のVC++ >>717
リテラルという言葉に「文字列」的なイメージを持っているならそれはなくした方がいいよ >>717
さらに追加
言うように3や3.14を定数と呼ぶとしても、リテラルと呼ぶことを排除できないと思うよ。
例えばこうなる。
「ソース中に3や3.14などの定数を記述する場合は数値リテラルを用いる。
数値リテラルは8進数、16進数、10進数の3種に大別されそれぞれ以下の形式である」
など。 そうなの? TIのCCSってのを使いはじめたところだが、warning出まくりでいやになる。
TI独自の問題? それとも警告レベル下げてるんじゃない。
問題なしだなんてとんでもない。問題大ありだよ。
そもそもC++ってCompileが全く通らない。なんでこんなにいちいちエラーをだすのかと腹が立つ。w >>714
c でも c++ でも const char * 版だけ作っておけばいい >>721
>「ソース中に3や3.14などの定数を記述する場合は数値リテラルを用いる。
>数値リテラルは8進数、16進数、10進数の3種に大別されそれぞれ以下の形式である」
違和感あるのは俺だけ?
「ソース中に3や3.14などの定数を記述する場合がある。。
定数は8進数、16進数、10進数の3種に大別されそれぞれ以下の形式である」
このほうが自然とおもうが、、、 俺はこっちの説明の方がしっくりくるな。リテラルと定数は意味合いが違う。
https://ja.wikipedia.org/wiki/定数_(プログラミング) >>725
一般的な意味での定数なら8,16,10進数に限らず3進数だろうが78進数だろうが好きに考えることができるけど、ここで8,16,10進数だと限定していっているのは、あくまでもC/C++の構文の要素である「数値リテラル」な訳だから、全く別の概念として明確に区別して考えた方がいいよ。
言語仕様のBNFとか見てくればもう少し理解できるようになるかも。 Wikiの説明はわかりやすいね。
でもconstのサンプルにはメッセージテーブルとかが良くかいてあるけど、ROM配置
じゃなくてRAM配置になるんだね。組み込みだとRAMが少ないから使えない。
constは役立たずというか貴重なRAMを消費する邪魔もの。 そういう話ではなく
コンピュータサイエンスにおける「リテラル」の用法についての批判でしょ。
恐らくコンピュータサイエンスを学び始めたばかりの日本人が、
リテラルという用語を使い始めた英米の専門家に対して行う、
英語として不自然である、という批判。 >>724
組み込み観点ではそういう考え方はまずいんじゃない?
なるべくconstは使わない方が良いような気がする。RAMが貴重だからね。 >>728
一体どこをどう読んだらそんな結論になるんだよ。
頼むから断定調で嘘を撒き散らさないでくれ a = a+10;
の意味も分からない人も、受け入れろよ。 >頼むからまずはcの基本を勉強してくれ
これが基本じゃなのか? 高度な質問をしているつもりはないが、、、
頼むからまずは基本に答えてくれよ。
まずVSなど他のC++はしらない。自分の感想はTIのCCSコンパイラについてだけ。しかし一般的に
組み込み系には通じると思う。
const 定義すると.bssに配置される。.bssはRAMである。組み込みマイコンではRAMとROMに分かれて
いるがRAMは非常に貴重だ。ちなみに今使ってるCPUは4kしかない。ROMは256kバイトある。
constでメニューテーブルなどを書くのは愚の骨頂だろ。そもそもconstなどなければこういう間違いは起こらない。
故にconstは有害だ。
どうだ理路整然としてるだろ。 >>739
> const 定義すると.bssに配置される。
んなこたーない。 トイレは水を大量に消費する。
ここには十分な水がない。
よってトイレは有害だ。 constだけで飯が3杯食えるスレってあったよな確か。
飯一食1000円とすると、3杯で3000円。
constには3000円の価値があるってことだ。
しらべえによると、3文は90円だそうだから、早起きの33倍、constのほうが価値があるってことだ。 >>741
そういうトイレは有害だ。ただしい。
結局んところconstはリードオンリーの意味しかない。リードオンリーのテーブルを作るのであればconstexprを
使えばいい。
リードオンリーの変数って何か意味があるんだろうか? 先ずは変数でありながら変更できない
のだから、実質的には変数ではない。本質的に存在自体が矛盾している。
たとえばリードオンリーであってもロックしたりアンロックできるのであれば意味がある。一旦ロックしたら
そのまんまってのでは、録に役にたたない。 >>740
ん。それは矛盾するだろ。基本的にC++のconstは変数だ。だから初期値は代入する。
それ以後はアクセスできない。少なくともRAMに配置する変数だ。ということは言える。
.bssに配置されるのかどうかはリンカでコントロールできるのかもしれない。ROMにだって無理やり配置は
可能だ。そういう無理やりのことをいってるのではない。あくまで自然なありかたとしてのconstだ。 >>745
言いたいことはわかるが、チャンと説明してみて、自分の間違いに気が付いた方がいい。 変数じゃなくてもメンバはconstで修飾できるぞ。 変数のconst,
文字列リテラルのconst,
メンバー関数のconst,
関数の仮引数のconst >>749
それは知らなかったが、その肝はなんなの? 結局はリードオンリーってディフェンスしたいって
ことではないの?
物理的に書き込み可能ならリードオンリーにしてもディフェンスになんかならないでしょ。
ディフェンスするならライトプロテクト機能がどうしても必要だからね。
アクセスできないようにするには、Privateにして不可視にすればいい。これでディフェンスになる。
グローバルにさらしてなお且つリードオンリーにしておきたい変数がはたして必要だろうか?
必要性はないと思う。
具体的にどんな意味があるのよ。 >変数じゃなくてもメンバはconstで修飾できるぞ。
出来て何の意味があるのかということが知りたい。意味がないなら邪魔だな。 メンバ関数プロトタイプの後ろをconstで修飾すれば、その関数の中ではthisがconstなポインタになり、
その関数の中ではconstではないメンバー関数は呼べなくなる。
つまり、constキャストを使わないと、thisを変更できなくなる。 >>752
あなたの言葉を借りるとconstはコンパイル時に「ディフェンス」するので
ランタイムで「ディフェンス」するよりも少ないコストで問題を発見できる
これは意味があることだ 関数の仮引数の型をconstで修飾すると、対応する実引数は変更できなくなる。
ただし、その仮引数にconstではない引数を渡すことはできる。
const付ければ多分変更されない。変更しようとすると、多分コンパイルエラー。 struct X
{
void func1();
void func2() const;
};
func1からfunc2を呼び出せるが、その逆はできない。 void func(const int& n)
{
...
}
funcの内部では(constキャストしないと)nは変更できない。多分。裏技使えば出来るかも。 >>739
> 自分の感想はTIのCCSコンパイラについてだけ。
マニュアルで .cinit section を検索しろよ >>754
説得力がありそうな意見だが、残念ながら意味がよくわからないので一寸調べてみた。
2のことかな。
メリット
1.参照渡しに const 修飾子をつけることにより、引数の中身を書き換えないことを宣言することができる。
ポインタ渡しに const 修飾子をつけることにより、引数の中身を書き換えないことを宣言することができる。
2.const オブジェクトを引数にすると、そのオブジェクトのなかで呼び出せるメソッドは const メンバ関数のみ。
1はたしかにメリットがあると言わざるを得ない。
2は使い方次第だな。自分の場合はわざわざそこまで面倒なことはしない。 >>759
自分も最近しったんだが、組み込みで使うとC++は非常に効果を発揮する。(らしい。あまりできてない、、、)
すくなくても、クラスやnamespaceを使えるだけでも大いに助かる。Cと滅茶苦茶相性がいい。
ごちゃ混ぜでもスパゲティでも何ら問題ない。
組み込みでは絶対にC++を使うべき。 >マニュアルで .cinit section を検索しろよ
ありがと。検索してみます。 >>752
お前、ほんとド素人なんだよな
しったか素人は単なる荒しと変わらんわ。 邪魔にしかならない >>746
君は何も知らずに妄想だけから判断して>>730の考えに至ったわけじゃん。>>714からの流れでね。
関数の引数を char* と const char * にしたときの違いは、
君が勘違いしている、ではなく、なにかを読んで知ろうともせず
自分だけの想像で決めつけているような「このポインタが定数(変更不可)かどうか」ではなく、
ポインタが差している char 値が変更不可かどうかなんだ。
で、
君の考えはおそらくここに書いてないものも含めて8割がた
間違ってるから誰にもそれを一々教えることは無理なんだよ。
だから本を読むとかして基本を学んで欲しい。
今の君は想像で英語に文句つけてるくせにアルファベットも知らない子供みたいな状態。 >高橋マナ著やさしいC++から始めたほうがよい。
C++は使い始めたばかりでよくわからないが、多重人格的で昔のC++と最近のC++が混在している
気がする。C++は糞って言ってる人は昔のC++をみていて、C++は最高って言ってる人は最近追加
された仕様を見ていると思う。
だからC++は基礎からやると駄目な言語だね。基礎は飛ばしてしまったほうがいい。
追加された仕様部分が秀逸だね。
だからあくまでも自分の意見だが「やさしい、、、、」ってのは寧ろ難解で駄目なのが多い気がする。
特にC++の生みの親が書いたような本が最も駄目だと思う。 ID:p/77GMIT
もうこいつの相手をするのはやめよう。 単なる荒しだわ。 ここで終わり >>767
>君が勘違いしている、ではなく、なにかを読んで知ろうともせず
>自分だけの想像で決めつけているような
ここ表現が変か
何も調べてないんだから単なる妄想であって勘違いですらないということ。 >>767
だれも最初は子供だからね。
視野が狭いのであって、思考がまちがっているんではないというところに気が付いてほしい。
だから視野が広がれば正しい結論にいたる。
そして結論は761 >>768
C++は近年追加された仕様の方が複雑怪奇で迷走しているという意見もあるし、勝手な思い込みで基礎を蔑ろにするのはやめた方がいい。
constの理解についても、組み込みのCをやった経験に基づく自分の経験と思い込みを当然のものとして他人の話を聞くから理解が進まないのでは?
RAMにおくかROMに置くかとかも本来はC言語としては未定義とか処理系依存な部分であって、組み込みにおける常識をベースにCの言語仕様を理解しようとするから齟齬が生まれるのだと思う。 >>761でよかったのか
まあ腑に落ちたようでなにより 組み込みだってconst変数がRAMに置かれるなんて常識は無いよ。この人の思い込み。 このスレにいるような低学歴知恵遅れは
引数だけでなくメソッドにもconstつけるべきというのすら分かってない
クラスの引数にconstつける意味を分かってなさそうだからな セクション配置の話なのにメソッドのconst関係ねーだろ
意味わかってないのはてめーだ、いつものことだが bss セクションは、リンカの文書を見れば?
メモリ配置と、文法のconst は関係ない。
基本的に、言語の文法と実装は、関係ない
実装は、JavaScript の文法に関係ない、DOM とか
できる限り、const を使うべき!
使っても、マイナスにはならないから
たぶん、Effective 本にも書いてある >組み込みだってconst変数がRAMに置かれるなんて常識は無いよ。この人の思い込み。
そのことを初心者にもわかるように詳しく説明してみてください。といっても解り過ぎている人には
初心者が何がわからないのかわからないとおもう。解らない人はどこまでもわからない。なので
質問を変えて差しあげます。
質問1.constは多用な機能がある。そしてその機能を実現するには最初の一回だけは書き換え
可能である必要があると思うが、もしconstをROMに配置してその機能をどう実現すればいいのだろうか?
実現不可能だとおもう。
このことが正しいならconstは当然RAMに配置されるのが常識だろう。いかがだろうか?
質問2.もしconstが一度も書き換え可能である必要がないとすれば、constはROMに配置
されるべきだろう。だからconstは必ずROMに配置すべきだというのが常識となる。この考えは
どこがまちがっているだろうか?
質問3.質問1と質問2の前提はどちらが正しいのだろうか? 完璧な質問のつもりだったが、質問を書いてみて今初めて見落としている穴が分かった。 >>772
C++は低レベルの処理に向いているのだから当然のように処理系のハードとの接点が多い。
処理系依存の部分はC++でフォローできないというだけで、だからといって処理系を意識しないでいい
ということにはならない。C++を使う場合には処理系を強く意識する必要がある。
>できる限り、const を使うべき! 使っても、マイナスにはならないから
処理系を強く意識するなら、こういう結論にはならないと思う。constは意に反してRAMに配置され得る。
組み込み系においては、RAMを多用すればすぐにRAMがパンクする。
constはいくつかのメリットがあることは解ったが、無条件に使えばやはり有害になる。少なくとも自分が使った
限りでは滅茶滅茶有害だった。
では被害を少なくするにはどうすればよいか? それに答えてほしい。
static const char* s_A; // -> BSS section
static const char* s_B = "b";// -> Data section
static const char* const s_C = "c";// -> Data section
static const char s_D[] = "d";// -> Read only Data section
static char s_E[] = "e";// -> Data section
static char s_F[128]; // -> BSS section
const char* s_B = "b";// -> ここで嵌った。これは.bssに配置される。 ID:mI2pOyKp = ID:p/77GMIT すいません、C++でゲームやGUIアプリなどを開発したいのですが
メソッド抽出やクラス設計といったプログラム設計に関する書籍って
どんなものを読めばいいんでしょうか?おすすめとかありますか?
ググっても、プログラム設計の本があまり見つかりませんでした・・
デザインパターンに関するものはあったんですが
もうすこし初歩的な内容のものがあれば教えてくださいm(__)m >>784
L'\0' はUnicodeだから、必ず2バイトなので、 0x0000 >>786
ワイド文字の内訳は未定義で、 Unicode になるとは限らないし、その大きさも決まってない。
2 バイトになって欲しいなら L ではなく u を使うと UTF-16 になることは保証されるよ。 >>782
挙げられた例でconstの付加によりRAM使用量が増えている例が見られなくて
「マイナスにはならない」が正しいように見えるんだけど、何を見て有害だと言ってるの? >>782
> const char* s_B = "b";// -> ここで嵌った。これは.bssに配置される。
s_Bはconst宣言されてない只の変数だからいいとして
"b"がconstだけど.bssに配置されるってこと? >>785
他の言語で造ったことあるか?
それがまだでいきなりC/C++ならやめとけ >>785
The Craft of Text Editing それ、C++でもないただのCでEmacs風エディタ作るっていう古臭い本だろ。
しかも一般的な設計論みたいなものはほとんどなくてエディタの実装テクニックがメイン。 >>793
普通はな、本を勧める状況ってな、
相手は読んだことがないのが当たり前なんだよ。
主題が違う本を挙げるからには、
どういう点で好ましいのかくらいは書いてくれ。 初心者です。
bool変数hogeの真偽で反対の代入をする場合につきまして、
int a, b;
if (hoge) { a=1; b=2; } else { a=2; a=1; }
と
int a=1, b=2;
if (! hoge) { a=2; a=1; }
はどちらのほうが好ましい書き方ですか?
完全に好みの問題ですか? >>797
偽(false)の時だけならif(!hoge){...}の方。 新スレを作りました。利用してください。
0からの、超初心者C++相談室
https://mevius.5ch.net/test/read.cgi/tech/1542002113/
***********************************************************************
1 名前:デフォルトの名無しさん[] 投稿日:2018/11/12(月) 14:55:13.35 ID:Tf74ZWQr
何にも知らない0からの出発、超初心者のためのC++相談室
*********************************************************************** >>798
すみません
>>799
ありがとうございます
>>800
超初心者用の専スレがあったんですね。ありがとうございます >>791
ありがとうございました。読んでみます。
プログラミングの良書って絶版になること多い気がしますが気のせいですかね・・。 int a=1;
int b=2;
if (!hoge) {
const int c = a;
a=b;
b=c;
}
俺だったらこうかな。 >>797
int a, b = 2 - !!hoge, 1 + !!hoge; ここは、初心者を歓迎するスレ
初心者を虐めてどうする >>807
最近やたら気になるみたいだけど、なんで自分は初心者に回答してあげないの? >>797
多人数で開発する場合は、前者のほうが好まれると思います。
可読性が高いのでコードレビューしやすいですし、改修もしやすいです。
後者は、1行目と2行目の間で、aかbの値を変更する改修が入ってしまうと
2行目のif文に入らない場合に、望む結果が得られません。
プログラマになりたいとかでなければどっちでもいいと思いますが
難しい書き方をすると、時間経って読み返したときに、
自分でも何を書いたかわからなくなりますよw >>797
else を使わなくて済むのなら、そうしたほうがいい、とはよくききます >>797
状況によっても違ってくると思う。 一般的には前者だろうけど、
{ a=2; a=1; } が例外的な場合として特別扱いしてるってことを強調したい理由があるなら後者で書くこともあるかもしれん。 いや、効率を考えたら断然最初の else を使う方では?
後者のやり方では hoge が偽の場合、無駄な代入をすることになる
もっともコンパイラが賢ければ無意味な代入を端折るコードを生成するかもしれんけど すまん自己レス
> もっともコンパイラが賢ければ無意味な代入を端折るコードを生成するかもしれんけど
これはムリだった。てことでやっぱり前者 >>814
clangで試したらきちんと最適化されたぞ int a=1;
if(!hoge){
a=2;
}
のa=1は通常の代入じゃないからね。
これは基準値で初期化しんだからよ。
こっちのが効率は良いよ。 int a = hoge? 1 : 2;
はどう? 多分タイポでa,bの値を条件によって入れ替える処理だと思うぞ。 int a = 1 * (!hoge) + 2 * (!!hoge);
線型代数 >>815
どういう最適化?
初期化されても参照される前に代入が起こる可能性があるから
hoge の判定の後まで初期化を遅延させる、つまり実質 else を使ったのと
同じコードが生成されるということかな?
そこまで出来そうな気もしなかったのだけど 初期値として意味があるなら後者でいい気はするが
なんか例が微妙というか、プログラムの流れがなんか不自然 だよね。
だからやっぱタイプミス(タイポ)で条件によってa,bを入れ替える/入れ替えないを切り替える処理と見た方が自然。 >>822
797の後者のコードがLLVM IR 2命令に最適化される
%2 = select i1 %0, i32 1, i32 2
%3 = select i1 %0, i32 2, i32 1
%0がhoge、%2がa、%3がbにあたる >>825
ありがとう。なるほど、すばらしい
これをまんまC/C++に書き戻すと
int a = hoge ? 1 : 2;
int b = hoge ? 2 : 1;
ということかな
でもこれだとhoge を2回チェックしてるので却って非効率な気もするけど
まぁ LLVM はまだ中間形式だから、これをターゲットコードに落とすところで
hoge の判定を一回で済ませるようにさらに最適化するのは簡単そうではあるね とは言え C/C++は効率ファーストな言語なんで、最適化を当てにして
ユルいコードでOK、てのも如何なものかという気はする
最適化は所詮、処理系依存だし
まぁ >>823 の言うように、その値で初期化することに強い意味があるなら
その書き方を優先する、そういうトレードオフがあることは認めるけど hoge ? a = 1, b = 2 : a = 2, b = 1;
ができればな >>829
もちろん原則論に過ぎないよ
あと、原則論と言えば「変数は定義時点で必ず初期化せよ」というのもあるわけで
初期化忘れを防ぐためにそういうコーディングルールを設けている所も多いはず
その場合は後者の方が望ましいことになる
初心者はむしろ効率より堅牢性を重視した方がいいかもね inline void debug_pulse(int no){
#if(DEBUG == 1)
switch(mode){
case 0: pulse(A0); break;
case 1: pulse(A1); break;
case 2: pulse(C5); break;
case 3: pulse(F0); break;
}
#endif
}
1.この場合 debug_pulse(3);は pulse(F0)と同じになる。
2. #define DEBUG 0 にすると全て跡形もなく消える。
1,2は正しい? 1.は正しい。
2.この世の全てが無くなるとは思えない。質問が不適切。 >2.この世の全てが無くなるとは思えない。質問が不適切。
質問の意図は
inline void debug_pulse(int no){ }はコードを生成しない。これは正しいか?
である。
質問の理解が不適切。 >>841
エラーになるのでコードは生成されません mode の出所は? A)no の typo B)別途関数の外に居るし int mode;
void pulse(void);
int A0;
int A1;
int C5;
int F0; modeがどうかは質問の趣旨と関係ないのでどうでもいいが(modeがglobalとか適当に)
inline void debug_pulse(int no){
switch(mode){
case 0: pulse(A0); break;
case 1: pulse(A1); break;
case 2: pulse(C5); break;
case 3: pulse(F0); break;
}
}
か
inline void debug_pulse(int no){
}
か
にしかならないから
1.は「ならない」
2.は「消える」 ああ 2. で消える条件は
debug_pulse() を呼んでる部分が無いことが前提だから
2. 「消える」「消えない」どっちとも言えない
だな >>846
inlineなんで、消えるか消えないかはアドレス必要な操作をしてるかどうか inlineをどう扱うかなんてコンパイラ次第
どんなコードが吐かれるかが知りたければ
吐かれたコードを見るのが一番 inline void debug_pulse(int no){
#if(DEBUG == 1)
switch(no){
case 0: pulse(0xA0); break;
case 1: pulse(0xA1); break;
case 2: pulse(0xC5); break;
case 3: pulse(0xF0); break;
}
#endif
}
1.この場合 debug_pulse(3);は pulse(0xF0)と同じになる。
2. #define DEBUG 0 にすると全て跡形もなく消える。
1,2は共に正しい? そもそもpulseがなんなのかわからんから
なにが書いてあるのか意味不明 次スレからは、
【初心者歓迎】C/C++室 Ver.103【環境依存OK】 を、
【上級者用】C/C++室 Ver.104【環境依存OK】
にした方がいいな。 いいかお前ら、これから>>852が理解できないことは一切書いちゃだめだぞ。
ここが初心者専用でなく初心者歓迎であってもだ。
回答するのはお前らだからな。 >>852
@すでに上級者スレはありますが?
Aそもそも上級者と初心者の境目をどう定義しますか? >>857
それは>>855Aの答えだけですね、@はどうですか? くだらないないことを、グダグダ突っかかり続けるのが、5ch民のクセ。 >>859
>>852 の提案が一番くだらないのでは? >>852が初心者向けの回答すればそれで解決だろ。アホ草 そもそも論言っていい?w
なんで初心者でも上級者でも質問したらきちんと回答してくれるこのスレがあるのに、自分が気に入らないからって勝手に新スレ作るの?
そういうのを躊躇なくやれちゃう人が本当に怖い・・・ >>863
そうそう、そうですよね
初心者には初心者のための回答がつき、上級者には上級者にふさわしい回答がつけば、それで必要にして十分ですよね
なんでスレを分ける必要があるのですか?>>852 今までの、他者排除姿勢から、よくも>>866が書けたもんだ。 他者排除だって?誰が?QZが?
被害妄想激しすぎるんじゃないか? >>867
>他者排除姿勢
とても興味があるのであえてお聞きしてもいいですか?
私のどういう点に「他者排除姿勢」を感じたのでしょうか #include <stdio.h>
int main() {
float f = 262143.98;
fprintf(stdout, "%f\n", f);
f += 0.01f;
fprintf(stdout, "%f\n", f);
f += 0.01f;
fprintf(stdout, "%f\n", f);
f += 0.01f;
fprintf(stdout, "%f\n", f);
return 0;
}
// why 厚切り json >>875
規格では決まってなかったと思う
まあたいていIEEE754の単精度だけど 様々な処理系依存についてそれぞれ具体的に何に依存してるのかってどこで調べられますか?
ソフトを作って配布するにあたって、ユーザーの環境をwindows7以降のPCに限定するとして
ユーザー側の環境に依存するもの
ユーザー側の環境に依存するがwin7以降のPCでは共通なので実質非依存とみなせるもの
コンパイル側の環境に依存するのでコンパイルしてしまえば非依存とみなせるもの
に分けて調べたいです >>878
まとめて書いてある所なんか無いよ
普通はコンパイラの範疇なものは実行環境に依存しない
一緒に提供しない外部のコードを使う部分(DLL, API, ドライバ)は依存する
と思っておけば良いけど
環境を判断して動作を変えるコードもあるし
実行速度は当然環境に依存する
特定の環境の場合にタイミング依存で発生する問題もある
確実に実行環境に依存しないなんて確証を得られるコードなんてごく限られた範囲になるんで
そんなものに頼らず
出来るだけより多くの環境で評価するのが望ましい README (.txt) (.md) (.rst) 某本で読んだんだけど、クラスの中にポインタ変数もたせる場合って、コピー禁止にするのが一般的?
コピーコンストラクタを書くのがめんどそうだし、そもそもクラスを代入やコピーをあんましないよね? >>882
そのクラスがコピーできるようになっているべきかどうかは個別に判断すべき話で、クラスの性質による。
コピーできない (コピーすると不整合が起こる) ようなデザインならコピーするなって言うだけじゃなくて
コピー禁止 (コピーコンストラクタの削除) にしておいたほうがうっかりコピーしなくて安全だねってだけの話。 排他主義は当然
低学歴知恵遅れは板から排除するベキ >>883
> そのクラスがコピーできるようになっているべきかどうかは個別に判断すべき話
これ、全く尤もだし大事な事だと思うんですけど、判断基準を学校や職場で教えてないんですかね?
メモリが少ない組み込み環境だと選択肢はあるけど、C++でアプリを組むような環境だと、
- シングルトンはコピーしない
- それ以外はコピアブル(ディープコピー)にする
一択だと思うんですが。 >>884
君の辞書には排他主義という単語があるのか? >クラスの中にポインタ変数もつ
これは、pimpl (pointer implement)デザインパターンだろ
pimpl インスタンスの遅延初期化だろ。
こういうのは普通コピーしないし、コピーするとインスタンスを共有して危険になるとか
遅延初期化するようなものは、非同期読み込みとか、何か失敗する可能性が高い、ヤバイもの
1回目は、ファイルから読み込んで、2回目は、キャッシュから読み込むとか、挙動が変わったり
pimpl を使っていれば、普通と違うから、ヤバイと思っておいた方がよい。
pimpl を使うには、何か理由がある >>885
原則としてはその意見は正しいと思う。
特別な理由がない限りコピーは出来るべきだ。
その上でコピー可能にするための手間と使い勝手のトレードオフ、
要するに「割に合うか」という判断は実務的なことだから、一律には言えないと思う。
コピー可能に出来るけど、コピーする箇所が一個もなかったわっていうような結末だって
有りうるだろうし。
そういう見極めに簡単な基準を設けられるのなら苦労はないわ。 >>887
pimplはAPIと実装を切り離して抽象化するためのもんだから、遅延とかキャッシュとか
実装詳細が関係しちゃいけないんじゃないですかね。
例えばマルチエージェントシミュレーションとかで、個々のエンティティの実装をpimplで隠した上に、
エンティティの複製は普通にやりますし。 >>888
> コピーする箇所が一個もなかったわ
あっそうかっ >>888
> そういう見極めに簡単な基準を設けられるのなら苦労はないわ。
私は古い教育しか受けてないので、過去については全く同感なんですが、
最近はもっと抽象化してるんじゃないかな、と思ったんですよ。 今はmoveがあるからとりあえずコピー禁止で作るな。
複製したオブジェクトが必要になる機会はあんまりない気がする。
vectorに突っ込んで連続したメモリに割り当てたいときとかかな。 >>892
read-copy-updateとか、マルチスレッディングで使うんですよ。
(スレッド間で同じ領域にアクセスすると、誰かが書き込むときにロックが掛かるから、
ポインタの参照先もコピーしてしまった方が良い) pimpl は、DI(dependency injection)でも使うか >>892
私も>>888で言われるまで気付かなかったんですけど、個々のエンティティはコピーしても
シミュレーション系全体をコピーする、とか、大きなオブジェクトをコピーするときって確かに無いですよね。
むしろ万一コードが走ったらレスポンスが遅くなるから禁止すべき。 でかいオブジェクトはコピーじゃなくてデータベースに入れてリビジョン管理するべきだよな >>891
コピーコンストラクタって言語機能があるから勘違いしがちだけど
コピーってオブジェクト指向一般的に言えば全くもって汎用的な処理じゃないんだよね
むしろ無理にコピー可を要求するとおかしくなったりパフォーマンスに悪影響することの方が多いぐらいだ
だから、C++より進化したオブジェクト指向言語、例えばC#もJavaもコピーコンストラクタなんてサポートしてないだろ?
なんでまあ、基本的にはコピーはサポートしなくていい
そのクラスの要件としてコピーのサポートが必須だとはっきり分かったときだけサポートすりゃいい >>898
>C++より進化したオブジェクト指向言語、例えばC#もJavaもコピーコンストラクタなんてサポートしてないだろ?
それはクラスは問答無用でヒープに置くことに統一した結果なのでは? C#には構造体があるがそれもコピーコンストラクタなどサポートしてないね
オブジェクト指向にはほとんど不要だから IClonableが用意されているのはそれが必要だと判断されたからだわな >>897
循環参照や並行処理や、今や制限しか思い浮かばない…… コピーコンストラクタなんて使ったことないよ
関数の引数も構造体はポインタで渡すべきだし、関数からの返り値も構造体で返すべきではない
あんなのは使うべきではない あるクラスのオブジェクトを静的/動的に確保した場合の互いのメンバ関数処理速度の差ってどれくらいなもんですかね
処理の規模にもよるのですか? 今プログラミング言語C++4第四版読んでるのですが、中級者なのですが1ページから読んでます
テンプレートはあまり使ったことがなく、テンプレートの章を読んでいるのですが理解出来ているのか出来ていないのか分かりません
皆さんこの本はどんな感じで読みましたか? テンプレートは大分前に読んだが、ぜんぜんスマートだとは思わんかったしプログラムもでかくなりそうだったし
くだらねえと思って、読むのやめたよ。 別に使わなくてもプログラム出来るしな ID:lehzCciN
ID:jIxWA8zR
ちょっとだまってて テンプレートは書くのはちょっと難しいというかアレだが
使うのは簡単だから、まずstd::vectorとか使ってみれば?便利だから
使い方が分かれば作り方もわかるようになるだろう
あとコピーの話でもめてたようだが、オブジェクトのコピーはC++の特徴だからなぁ
C言語からのもので、構造体が値型と同じようにコピーできるっていう
そのおかげでスタックにオブジェクトを確保してRAIIが出来るまぁこれも特徴的だわ
一方で配列が=でコピーできないのもC言語からのもので
構造体より配列の方が他の言語で言うところのオブジェクトと似たような仕様になってるw
参照するとポインタに格下げになるのもJavaやC#のオブジェクトと一緒だね もしC言語の構造体が配列の仕様と同じように
アクセスしようとするとポインタに格下げになってコピーできない仕様だったのなら
C++のクラスはもうちょっとモダンな仕様になってたかもしれないよね
値渡し出来ないからコピーの事を考えなくてもよいし
GCないからキツイか >>911
> 使い方が分かれば作り方もわかるようになるだろう
コンパイラの使い方が分かっても作り方が分かるやつはそんなに多くないが… その場合でも、例えばC言語のコンパイラを作りたいとき
C言語の使い方を理解せずにC言語のコンパイラを作るより
C言語の使い方を学習してからC言語のコンパイラを作る方が
賢明だろ >>906
性的・童貞的の差異よりも仮性・真性の差異を問題にすべきかと >>909
lisp のマクロとC++のテンプレートとは、どっちの方がイケてますか? >>911
>配列が=でコピーできないのもC言語からのもので
私はときどき夢想します、配列が=でコピーできたとしたら、どんな世界観がふりかかってくるのでしょうか? >>917
もしそうなら、配列のサイズの情報が関数プロトタイプに付属していただろう。 >>915
訂正します
静的・動的の差異よりも仮想か非仮想かを問題にすべきかと思います >>918
実体化を明示すれば書けるよ
使う奴を全部列挙しなきゃならないけど、ロジックを共用できるのは大きい #include <stdi.h>
int main(void)
{
int i, j;
for (i = 1; i <= 9; i++) {
for (j = 1; j <= 9; j++) {
printf(" %2d", i * j);
}
printf("\n");
}
return 0;
}
あるサイトを参考に
簡単な九九の表を作ると
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15...
...
...
(略)
このようになると思いますが、
隣の数字を参照にして足して
3 5 7 9 11 13 15 17
6 10 14 18 22 26 30 34
9 15 21 27 33...
...
...
(略)
と、表示するには上記のサイトの様なプログラムをどのようにすれば良いのでしょうか?
宜しくお願いします。 >>924
別スレにも書き込んでたけどそっちでは相手にされてなかったね。
上記サイトと書いておいて、そのサイトが抜け落ちてるよ。コピペしたなら推敲もしような。
やりたいことは i*j+i*(j+1)を出力するということか? :-) 等、海外の顔文字(横向きver)
:-P でワンセットよ :-P
でひとつだよ。
頭を左に倒して無心になって見る。 この手の表現はネット検索でも探しにくいからなぁ。
検索ワードに含めることができない文字を使ってるかも知れんし。
Wikipedia で「顔文字」の「欧米型の顔文字」に例示されてるね。
P は大文字が普通なのか。小文字 p だと思ってたわ(てへぺろ)。 こないだTWITTERで orz の話題が流れてたわ。
「絵文字があるのにそういうので遊んでたんですね!」 → 「無かったんだよ (#^ω^)ピキピキ」 全くの素人なんだがスタックサイズ以上の巨大なクラスをローカル変数として宣言したら即オバーフロー起こす? まともなOSなら。
でもOSのない環境もあるし未定義。 スタックサイズのオーバーフローって普通、いちいちサイズ確認しながらエラー判断じゃなくて、
割り込み処理でやってるんだろ 環境依存
個々の話をしたいなら
> そのような質問は必ず環境を書きましょう 宣言しただけでアクセスもせず関数も呼ばないなら、
エラーにならないのがほとんどかもな。 自動変数を宣言しただけで使わないなら
最適化で消えちゃうこともあるかもな。 ああ、C++の標準ライブラリにLISPインタプリタが入らぬかのう…… TinySchemeのカスタムインタプリタ作った時、例外の扱いやら引数チェックやら面倒で面倒で。
どうせみんなやってるんだから、標準のAPIがあれば車輪の再発明をせずにすむのに。 #include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main(void)
{
string str;
getline(cin, str);
//cin >> str;
transform(str.begin(), str.end(), str.begin(), toupper);
cout << str << endl;
return 0;
}
このコードの「getline(cin, str);」と「cin >> str;」と「cout <<」
の部分にエラーが出るのですが何が原因かわかりますか?
別個にstd::を付けてもだめでした。解かる方いましたらよろしくお願いします。 GNU の公式なアプリケーション拡張用言語は Guile >>943
#include <string.h>
→#include <string> >>943
toupper は <locale> にある関数テンプレートと、 <cctype> に普通の関数がある。
どれだかわかんなくて混乱している。
toupper を [](char ch){return std::toupper(ch);} という風にラムダ式でくるむのが一番楽な方法だと思う。 > Guile
Cygwinの中じゃなきゃ動かないじゃないですかw
WindowsのGUIアプリのカスタマイズに入用だったんですよ。 >>947
Windows だけでいいなら、
言語処理系を組込んでしまうよりはインターフェイスを COM にしておいて
適当な (OLE オートメーションに対応した) 言語を使ってもらう方が簡単かも。 >>945
コンパイル通りましたありがとうございます!
>>946
レスありがとうございます。ラムダはC#のをちょっとかじったくらいなのでよくわからないです。 >>947
v8でjavascriptは?
自作アプリに組み込んでるけどwindows環境でも簡単に導入できる。 Windows なら WSH がすごく良い仕組みなので、
その枠組みをぜひ活用して欲しいと思ってる。 今は日本語や漢字にとどまらず、Unicodeで許されるあらゆる言語の文字を使ってるから、表現性はとても豊か(何がだ) [](){}と括弧揃い踏みなところがラムダ式の素晴らしいところ
キャプチャの必要性が分かるまで15時間も掛かった >>950>>951
今思えば全く勉強不足だった...
階層的データ構造(CADとか)はS式と思い込んでいたのよ #include <iostream>
#include <string>
using namespace std;
int main(void)
{
string x;
cin >> x;
for (int i = 0; i != x.size() - 1; ++i)
{
cout << stoi(x[i]) << endl;
}
} ⬆が動かないのですがどこが間違っているのかご教示下さい
C11は対応しています iはsize_t型にする。
文字コードや整数値に対しては、stoiは使えない。別の関数を使う必要がある。 >>957
念のために確認するけど C11 って書いてるのは C++11 の間違いだよね? >>956 が動かないってのはコンパイルエラーということだよね。
string x; だから x[i] の型は char で、
一方 stoi() が要求する引数は string であるからして... こういうことをしたいのではないか?
ここを cout << stoi(x[i]) << endl;
こうする cout << (isdigit(x[i])? x[i] - '0': 0) << endl; クラスの中の宣言部分で
var a = new classA(32);
がある時にこの生成時間を測るには
p1out = 1;
var a = new classA(32);
p1out = 0;
ってやってP1.1をオシロで確認したらいいのだろうか? スタック領域に確保した変数のメモリはその変数のスコープ終了時に開放される
静的領域はスコープが終了しても開放されない だがちょっとまってほしい
本当にそれだけだろうか? 静的領域は、アプリの実行前に確保する。
サイズも変動しない
スタック領域は、アプリの実行中に確保・解放する。
サイズも変動するし、領域を使い果たすと、stack overflow というエラーが起きる
事前にサイズがわからず、サイズが変動して、エラーが起きる可能性もあるので、
組み込み制御装置では、制限される事もある スタックの理解はCPUの動作原理から学んでいくとわかりやすいよ 組込だとスタック4つまでとかあるね。
下手に関数の中で関数呼び出し出来ない。
今はだいぶ緩和されてるけど、数が増えただけでPCほど緩くはない。 int num;
unordered_set<int> ust;
auto itr = ust.find(num);
itr == ust.end() ? ust.insert(num) : ust.erase(num);
とすると、
error: operands to ?: have different types
というエラーがでます
三項間演算子を使わずにif文を使って書くと普通に上手く行くのですが、なぜエラーがでるのでしょうか この前パソコンで100回くらいの再帰を書いたけど大丈夫だった
それともgccがよしなにやってんの? >>971
insertとeraseの戻り値の型が違うんじゃね? 三項演算子が絡んだ式の (条件 ? 値A : 値B) 部分で
値Aと値Bの型が異なると、三項式(と言う呼び方で良いものか)全体としての
結果の型が確定しないからダメって感じかねぇ。
どうせ値を使っていない式文だからいいじゃん、は通らないと。 >>974
そうだね。
値A、値Bともに(void)でキャストすればコンパイルできた気がする。
そんなことするくらいなら素直にif/elseにすべきだけど。 条件A ? (値A, 0) : (値B, 0)
とか?
if で良いだろ スタック領域は同じコンパイラでもオプションで変えられる事も多い(組み込みには言及しない)
末尾再帰だとループに展開されたりもするから(外から見た挙動が同じならC/C++はコンパイル後の表現を縛らない)、再帰イコールしぬとは限らない そう言えばC++20では[ , ]って形は多次元配列のために使われるんだな 型の違いでっていうのも判るが
結局評価だけして代入しないなら
(副作用を期待しないって条件付きだが)
最適化で消される行かも知れんな https://ideone.com/pUrvlb
VisualStudioCommunity2017 ver15.9.4でこのコードをビルドすると
「error C2440: '<function-style-cast>': 'int' から 'Lit' に変換できません。」
というエラーが10行目で出るんだけど、何が悪いんだろうか。 Parser() { reg(Lit{ 1 }); } → Parser() { ::reg(Lit{ 1 }); }
コレでいける
理由は知らん ubuntuで日本語含むファイル名を操作したいのでwoendirとかないのか探したんだけど見つからず、
wchar_tでファイル名処理した場合、いちいちmbstiwcsで変換するしかないの? utf8のままどーやってopendirするのさ?
それができないから困ってるのに
DIR *dir = opendir("hogehoge");
struct dirent *dp;
dp=readdir(dir);
としたとき,dp->d_nameに入ってるファイル名ってのはcharだよね
このファイル名に手を加えようとする(renameとか)と、utf8の場合、いったんmbstowcsでwchar_tにでもコピーするとか、
wstringにでもコピーしないと文字コードと格闘する羽目になるよね。
もし、
wDIR *wdir = woprndir(L"hogehoge");
struct wdirent *wdp;
wdp = wreaaddir(wdir);
とかできればsonomama
wdp->d_nameはwcha_tなので文字の先頭バイト見て何文字なのか判断するなんて余計な操作しなくて済むと思ったわけ。 bashで
for i in *; do
$newname=`echo $i| myprogram`
mv $i $newname
done
で済ませてたんだけど、myprogramの方は単に文字処理だけで、
置換とか文字列削除とかややこしいところはwstringに変換してた。
bashに任せてたディレクトリオープンや、ファイル操作までC/C++でやらせようとなると、
再度wcstombsとか余計なコピーが必要になってなんだか思いっきり損してる気分になったので、
なんかほかの手がないものかと? >>989
utf8 を wchar_t* に入れるのはただのアホやろ setlocale(LANG, "ja_JP.UTF-8");
setlocale(LC_CTYPE, "ja_JP.UTF-8");
char* utf8 -> mbstowcs -> wchar_t* wcs
wchar_t* wcs -> wcstombs -> char* utf8
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=vs-2017
https://mgng.mugbum.info/1014 無責任なこと書くけど、
Linuxならmountコマンドにオプション加えれば
ファイル名の文字コードをうまいこと透過的に変換してくれんか?
ファイルの実体に手を触れずにファイル名のコード系だけ変えたいなら、
struct dirent の d_name のバイト列をどう解釈するかの問題で、
ロケール関係ない話になりそうだし。 プロセス側から見たらふつうそれもlocaleに従うんじゃね? >>991
それは違うだろ
ファイル名をcharに入れてregex_replaceあたりの正規表現で再びcharに入れる場合はともかく
全角半角変換みたいに文字コードそのものをいじりたい場合はwchar_tに入れるだろ
全角文字コード -= '!'-'!'
みたいな変換しようすれば
char *pBuf = Bufとして、
*pBufの値に応じて
((*pBuf<<16) +(pBuf[1]<<8)+(pBuf[2] )&(0x00ffff
みたいなバイトの組み立てが必要になるじゃん
*pBufの文字コードに応じて
pBuf +=3だのpBuf++だのインクリメント幅の調整も要るし
いったんwcha_tに入れるのは何も間違ってないと思うが シェルからファイル名をfgetwsで受け取ってるうちはwchar_tとwstringで処理してから
またシェルに出力を返せばすむけど
opendirにwchar_t版がないんで、正規表現以外の処理して、
シェルに任してた部分をC++で全部書こうとすると、
>>993のいうようにmbstowcsとwcstombsで処理を挟んでやらんとどーしよーもないと思う c++builder10.3 community
IID_PPV_ARGSを使わない場合どうしたら良いか教えてください
何を入れたら良いのかわからないです
#include <windows.h>
#include <tchar.h>
#include <shlobj.h>
#include <shellapi.h>
#include <commoncontrols.h>
void __fastcall TForm1::Button1Click(TObject *Sender) {
IImageList *piml;
SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&piml);// pimlがNULLになる
SHGetImageList(SHIL_JUMBO, IID_PPV_ARGS(&piml));// 成功
} このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 180日 2時間 20分 26秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。