スレを勃てるまでもないC/C++の質問はここで 25 [隔離病棟]©2ch.net
基本的にポインタの値は低レベルではアドレス値だけど
機械語レベルではアドレスと言うものがCではポインタと言われているとは限らない 多分、根本的に、型というものが理解できてないんだと思うよ >>195
ちょっと待って。そこをはっきりさせてくれよ。 AならBだけど、BならAとは限らないってだけ
これぐらいは高校の数学で習うだろ
もしくはアップキャストは常に成功するけど
ダウンキャストは成功するかわからない、といったところか char *p のとき、
p はポインタ?それともポインタ型変数?
pに入っているのはポインタ?それともアドレス?
ポインタってどれ? >>199
pは(char)ポインタ型変数で、入っているのは(char)ポインタ値
ポインタ値の実態はアドレスでかつ整数値のことが多いってかそれ以外の環境は見たことも聞いたこともないな >>200
ありがとう。
ちょっと考えてたんだけど、やっぱりchar型ポインタとかint型ポインタってのはないんじゃないのかな。
インクリメントしたときにいくつ増えるかはポインタ変数の型で決まるだけだし。 >>201
char型ポインタ型だとなんか被ってるから省略してるだけじゃないかな
charポインタ型でもいいと思うけど。さらに言えばcharポインタでも通じると思う >ちょっと考えてたんだけど、やっぱりchar型ポインタとかint型ポインタって
>のはないんじゃないのかな。
int i; char c;
&i //int型ポインタ
&c //char型ポインタ >>195
>機械語レベルではアドレスと言うものがCではポインタと言われているとは限らない
具体例は? jmpだけ見せられたらそれはcだとgotoかな
もちろん関数ポインタもあり得るし、ほかにも逆コンパイル先はあり得る >>206
ifとかの分岐でもjmpは生成されるだろ 関数は飛んだあと戻ってこないとだめだからね
飛ぶ前のアドレスをpushして飛ぶ
そこがjmpとの違いなんだが...
まあ高級言語しか使ったことない人にはあまりそのあたりがわからないのだろう C/C++ とあんまり関係ない話題に乗るのは気が引けるけど…
メモリへの読み書きを避けるために
戻り先アドレスをスタックに積まないCPUもあるよね。
PCの値をレジスタにコピーしてジャンプ。
リターン時にはレジスタからPCにコピー。
ARMのサブルーチン呼び出し命令が "BL" だからって変態あつかいするな。 >>214
>戻り先アドレスをスタックに積まないCPUもあるよね。
RISC CPUだとだいたいそれだな
リンクレジスタというのが用意されててサブルーチンコールの戻り値がリンクレジスタに格納される
スタックに戻り値を積みたい場合は手動でスタックに積む
MIPS、ARM、POWER、SPARCなどみんなこれ 214 に補足。またもC/C++と無関係ですまぬ。
投稿時には意識していなかったけど、
BL命令で「さぶ」ルーチンだから辻褄は合ってる、かも。
流石ARMさんは紳士の国イギリスの会社だなぁ。 デバックの為自分の昔のコードを読むと
難しくて理解するのに時間がかかったりして
己の衰えを自覚するよな コーディングスタイルが変わっちゃってたり、
当時は精通していたアルゴリズムを使わないでいるうちに忘れたり、
別の場所で散々書いた注釈だからと省略した場所を直すはめになったり。 じゃ昔のコード読めなくなったら、プログラミングの勉強からやり直しだなw C++11なしで以下のプログラムがコンパイルできて2が出力されるようにしたいです。
どうかけばよいのでしょうか。
https://wandbox.org/permlink/NK5dYKZtrEBXN012 >>230
超ありがとうございます!(5時間悩んだ) 解決してるようだが
>>229
for_each(vsz.begin(), vsz.end(), boost::lambda::var(misz)[boost::lambda::_1]++); >>232
ありがとうございます!
boost::lambda::varの方はVCコンパイラでもビルドできました。
余談ですが、operator[]の代わりにstd::map<>::atを使えないか試してみたのですが
こちらは無理そうでした。 > 余談ですが、operator[]の代わりにstd::map<>::atを使えないか試してみたのですが
> こちらは無理そうでした。
・そもそもmap::atがあるのはc++11以降
・しかもmap::atはキーが存在しないと例外を投げるから今回みたいな[]の代わりには使えない
・それでやるとしてもboost::lambdaではbindを使わないとできない >>234
回答ありがとうございます。
ひそかに.atが使えないか調べていて
一日中やっても駄目だったので諦めたところでした。
自分の環境はVS2012でC++11が部分的に実装されている状況だったため
.atがないことに気づきませんでした。すみません。
bindを使う方法はboost::bindやboost::lambda::bind、boost::phoenix::bind
と、一通りやってみたのですが自分にはどうやってもコンパイル通りませんでした。 >>236
わざわざ調べてくださって本当にありがとうございます。
喉の魚の骨が取れた様な気分です。
キャストは思いつきませんでした。 組み込み系ってC++よりもCを使うことが多いと思うが、C++を使うと問題ある?
ROM 256Kbyte、Ram 8K位の場合だと、何か注意することある? 20年以上前はためらったが今はアセンブラなんてやってられんな
昔はハードに合わせて開発したが、今は開発に合わせてハード選べばいい つかC言語と言っても
直接アセンブラ・ニーモニックを埋め込める
インライン機能が用意されてる処理系あるし 普通C++だとRAMペースだろ。だから組み込みでRAMが8kとかでは使えないだろな。 そりゃISO-2022-JPならともかく、Shift_JISやUnicodeでは正当な文字ですからね。 変換時の文字幅にまるで無頓着な人が増えた、という話を聞くね。
環境が全面的にプロポーショナルフォントになったことも関係あるかと。
コピーしてペーストして一部書き換え、て手順のせいで
単語中で「半角」「全角」が混在したり、それに気づかなかったり。 半角カナに敏感なのって40代、50代以上だよね
未だに2chやってる奴いたんだ 1月11日
みたいに一桁は全角2桁は半角ってのもあるな OpenMPで#pragma omp sectionsの役目って何なんでしょうか?
#pragma omp parallelで並列領域を
#pragma omp sectionでスレッド処理(スレッド割当て)単位を
指定することは理解できました。
しかし#pragma omp sectionsが必要となる理由がわかりません。
なぜ必要なんでしょうか?
※
#pragma omp parallel sectionsって書けるみたいですが
まぁこれは本質ではないですよね?
#include <stdio.h>
int main(void)
{
#pragma omp parallel
{
#pragma omp sections // ←コンパイラに何を指示してる?
{
#pragma omp section
printf("Hello 1\n");
#pragma omp section
printf("Hello 2\n");
#pragma omp section
{
printf("Hello 3a\n");
printf("Hello 3b\n");
}
}
}
return 0;
} >>251
C99 の「指示付きの初期化指定子」かな? >>252
ありがとうございます。理解できました。 シングルトンにするのと、全部クラス変数、クラスメソッドで実装するのと
目的はあまり違わないような気がするんですけど、あえてシングルトンにする意味があれば
教えて頂けないでしょうか? 質問の意味がわからないが、シングルトンというのはインスタンスを一つしか持たない
ということ。クラス変数のようにインスタンスがいくつも作れると誤って2つインスタンス
を作ってしまう可能性がある。そうすると本来とは違う変数にアクセスしてしまう恐れが
ある。これをさけるんが目的。 >>255
レス有難うございます。
それは、インスタンス変数じゃないでしょうか?
クラス変数は同一クラスで共有される静的な変数なのでいくつも作れるものではないと理解しているのですが... 微妙に違うけど例えば自分の体重管理アプリを作るとする。「自分」は一人しかいないから、体重を格納する変数だかクラスは1つあればいい
家族の体重管理アプリなら、「家族」は複数だから体重の格納も複数になる
こうしたときに自分アプリはシングルトン設計、家族アプリはシングルトンでない設計と「呼んでるだけ」。元々みんなやってたことに専門用語っぽくネーミングしただけだよw >>257
それ、クラスがシングルトンじゃなくて、データが個人用(単一データ)か複数人用(配列/ディクショナリ)かって話だから、シングルトンとは違うような... 抽象メソッドにできるというのが一番の利点じゃないかな。 組み込み環境に C++ のコードを移植しようとしているんだけど、質問ってここでしていいのかな。
RAM の容量が厳しいので、 Flash にデータを持つように改造したいと思っている。
で、これは、C++ 的には定数でデータを持つだけで実現できるらしい。幸い組み込み環境ではリードオンリーでよい。
普段 PC 環境なら計算量の多いコンストラクタを経て初期化しているあるクラスのインスタンス群を、
PC 環境上で初期化して各フィールドの値をダンプしておいて、
組み込み環境では各フィールドが const になるようにクラスを改造したうえで
何かの方法でコンストラクタをスキップしてやりたい。これでRAMも計算量も減らせたらいい。
思いついた方法は、シリアライザというかコードジェネレーターを用意してソースコード上に定数群をたくさん定義して、
MyType i { cDataA, cDataB, ... }, j { cDataO, cDataP, ... }; のような記述ができるようにする、という感じのもの。
ほかによく使われている方法はある? あるいは、アドレスのキャストか何かでインスタンスの初期化を完了できる黒魔法っぽい方法もあったりする? って隔離スレなのか。まあ過去レス見た限りでは答えてくれているようなので… よろしくお願いします。 static char buf[sizeof(MyData)] = { ... };
MyData& data = reinterpret_cast<MyData&>(buf); static char buf[sizeof(MyData)] = { ... };
MyData& data = *reinterpret_cast<MyData*>(buf); ありがとう
{ ... } の部分をプログラムからうまく生成する方法はなにかあるだろうか? キャストで済んでいるのはとてもよさそうだけど、
PC 環境でのメモリ上での表現と組み込み環境でのメモリ上の表現は完全に一致するのだろうか。
アライメントというものがあるんだったような unsigned char *pb = reinterpret_cast<unsigned char *>(&data);
for (size_t i = 0; i < len; ++i)
printf("%02X, ", pb[i]); char *pch = reinterpret_cast<char*>(&data);
for (size_t i = 0; i < len; ++i)
printf("%02X, ", (*pch & 0xFF)); まそうですよね。再びありがとう。
アライメントについては各環境で実験して (offsetof(MyData, ...) が一致するか) いけそうなら試してみる。
エンディアンとアライメント(バイト境界)が一致してればきっと大丈夫だよね 助かる、これでとんかつ定食でも食べてくれ っ [ぺいぱる] floatを実数Xで初期化する際にfloatではその数を正確に表現できない場合、少し大きいか小さいかでXに近い値になると思います
そういう正確には表せない場合に、どうすれば初期化される値がXを下回らない最小の値となるようにできますか?
たとえば√3(1.7320508075688...)で初期化しようと float x=1.7320508075688f; と書くと
xの値が1.732050776となり√3より小さくなってしまうので、そういうのを避けたいです >>271
C/C++の標準機能では無理な気がする
というか、無理関数や超越関数でそういう丸め方が出来るアルゴリズムってあるのかな?
高精度で求めてから丸めるしかないような気がするが
運が悪いとそれでも下回らない最小にはならない 言葉足らずでしたが、標準やその他ライブラリの数学関数の結果として求めたいのではなく
数値リテラルとして初期化する場合に限ってもらっても結構です
閾値として使うのに、切り上げか切り下げかわかっていないと間違った結果が出て後で困ることになります
たとえば単純に閾値未満と以上のデータを別の用紙に印刷するプログラムを以下のように書いた場合
double result = calculation();
double threshold = √3
if (result < threshold) fail_list.add(result); else pass_list.add(result);`
print_to_paper(fail_list);
print_to_paper(pass_list);
計算精度に限界がある以上(閾値付近での)比較での細かい誤差は気にするなという人もいるでしょうが
それ以上に実際に紙面に載る値が要件に反する事態になってしまうと後々困ったことになるのです...
>>274
次善の策でそのことも考えますが、要件が変わった場合などに脆さが残りませんか? 閾値も比較対象も同じ精度なら不都合は起きない気がするけど
不都合が起きるとすると、計算過程での誤差が許容範囲内かどうかってことじゃないの?
どっちにしても無理数はどっが切らないといけないわけだし、扱える有効桁数の範囲で計算するしかない
ちなみに、
float x=1.7320508075688f;
は、代入の時点でfloatの有効桁数を超えてるから表示した時の結果と異なるのは当たり前
doubleだと有効桁数が15〜16桁程度ある。それでも不足なら、long doubleを使うとか、decimal型
を扱う外部ライブラリを使うとか (v-1ULP) <= X < v となるvを選びたいということかね?
その方法は知らんが、常に (v-1ULP) <= X < v か (v-1ULP) < X <= v のどちらかなわけだから
別に問題ないんでは?X≒vを上に組み入れるか下に組み入れるか決めりゃいいだけで。 説明のために>>276のプログラムをfloatに戻したものを考えると
(result < 1.732050776f)という比較ではresultが1.732050776fだった場合に
1.732050776は√3未満であるのに合格リストの方に載ってしまうということです
計算上の誤差があるとかdoubleの有効桁数が多いとかでなく
プログラム内の数値の取り扱いに関係なく、実際の紙の上では間違いが起こってほしくないということです
うまく説明できてるかどうかわかりませんが、実行時どの程度誤差を許容できるかは問題ではないんです
結果を見せた時に、どうしてこの値がこっちのリストに載っているわけ? 直しておいてくれる?
と言われれば、どうせ境界値付近の値なんてどちらのリストに載っていようと計算誤差もあるしいずれにしても正確とは言えないんですよ
では通じないんです...
≒をどちらに組み込むかを決めておくというのも、結局は事前に求めておく>>274の手法と同じ手間がかかりませんか
要件の数値(実数)が変われば、切り上げか切り下げのどちらであるかも変わってしまいますから
どちらになっているかを確かめなくてはいけないですよね そもそも、 1.732050776f と言う書き方が矛盾してでしょ
末尾にfをつけてるから、floatに変換してるわけだけど、1.732050776 はfloatの有効桁数を超えた表現だからこの比較自体がおかしい
1.732050776 と比較したかったらdoubleで計算すればいいし、もっと大きな有効桁数を求めるなら、long doubleなり、decimal型を扱えるライブラリでも使えばいい 1.732050776と比較したいのではなく√3です(√3という数も説明の便宜上です念のため)
ですからdouble型でも√3が表現できないのは変わらない以上は
floatをdoubleにしても問題の起こりやすさが減るだけで起こることに変わりないと思います
doubleを使うなら1.7320508075688...よりも多くの桁数を書くことになるというだけです(20桁以上?)...
私の場合有効桁数そのものが問題なのではなく、切り上げか切り下げを指定したいということです
あるいはどちらが行われているかがわかればそれで問題ありません(と思います)
加えるとほかの工程に渡す必要があるためdecimal等をサポートするライブラリの使用は非常に厳しいです 小さかったら、FLT_MIN / 2を繰り返し足せばいいんとちゃう? >私の場合有効桁数そのものが問題なのではなく、切り上げか切り下げを指定したいということです
それならその√3を求める関数の仕様に当たるべきでは。
標準の数学関数だと、丸め方式以前に1ULPの誤差も保証されているとは限らない。 >>281
√3との比較対象となる計算結果も、floatなりdoubleなりを使う計算過程で桁落ちは発生するでしょ? そっちは問題ないの?
閾値となる√3の桁落ちだけが問題?
なんにしろ、√3みたいな無理数を扱う場合は、有効桁数何桁、少数点以下何桁まで考慮するという前提がないと、それを扱う型の精度も決められないし、それがデータ設計者の役目だと思うけど ルート3に相当する数値を2乗して、3以上になればいいんだろ? >>285
√3と言うのは例として上げただけで平方根とは限らないみたいだよ >>279
丸める前の値は何?
文字列?double?数式? >>288
元データは文字列で、最大で有効数字8桁くらいの10進数の小数点数です
それを単にstrtofで読みこんで、計算過程もずっとfloatです
ですけど読み込み時の誤差も含めて計算誤差は特に問題にしなくてもかまいません
それこそ計算誤差があるから仕方ないで押し通すこともできると思います
ですが、計算結果を2つのグループに分ける際に、実数の閾値に対して忠実でなければならないということです
>>284
閾値も計算の精度も32ビットのfloatで問題ないです
なので閾値となるfloat値を事前計算すれば、とりあえずは済みます
(ですが事後の変更に備えて、安全な方策がないものかと思い始めたわけです)
>>283
閾値は実行時に関数を呼び出して計算する必要はありません
単に計算機で求めた桁の多い数字を使って意図通りにfloatを初期化できれば問題は解決です >>290
32ビットfloatの有効桁数は7桁しかないよ
√3は、小数部6桁の1.732051 までしか表現できないし、
例えば整数部の最大を4桁としたら、小数部は3桁までしか使えない
大丈夫? >>289
無理数を定数値とする方法は無いから片山の意見は一理ある 使ってる環境のfloatのビット表現を確認して、それで誤差なく表現できる閾値以下の最大の数値を求めて、それを定数として閾値にすればいいんでないの? 元の10進数の文字列に対して、
これを下回らない最小のfloatの値
これを上回らない最大のfloatの値
を求めれば良いの?
仕様をはっきりして floatの値と10進数文字列の大小比較が出来れば良い?