C言語なら俺に聞け 155
レス数が1000を超えています。これ以上書き込みはできません。
for(int i = 0, a = 2; i < 10; ++i) ...
同じ型じゃなくて
Cで
for(int i = 0, long a = 2; i < 10; ++i) ...
観たいに描く方法を教えて >>4
{
int i;
long a;
for(i = 0, a = 2; i < 10; ++i) ...
} for文で++iって書くやつは過去の学習に縛られ惰性で生きている臆病者 >>7
それを言っているんだ。 正しく自己を見つめ直せ >>6
i++ と書くと未来に縛られちゃうの?
つか、
for (略;略; ++i) と
for (略;略; i++) に違いあるの? C++はテンプレートと演算子オーバーロードの関係で前置で良い場合は全て前置にする。 >>8
言ってる意味がさっぱりわからん
何が不満なんだ? 禿げ(C++の神)から前置にしろと御神託があった。
SA: 禿4 pp.982 4回書き込んだだけで2位かよ。
ム板はこれから青森サーバーと呼ぶ。 前置は不可分にしてしまった継続処理くらいにしか使いみちがない特殊な演算子だからのう
c言語的にどっちでもいい場合とりあえず前置にして論理バグのスルーを防ぐみたいなやり方あるかもしれない for文の場合、インクリメントされるタイミングがブロックの末尾だから、後置の方が直感的な気がするね C言語しか知らなくて、学びながらプログラムの作成にチャレンジしてるものです。
fopenについて教えてください。
fopen("wb")で開くとポインタ(ストリーム?)はファイルの先頭で上書きモード
fopen("ab")で開くとポインタ(ストリーム?)はファイルの最後で追記モード
ということを知りました。
既存ファイルを開き、先頭部分のデータの一部を上書き、且つ、末尾にデータを追加したいと考えています。
この場合は、どっちか片方で開いてfseekとかでポインタ移動してしまえば、 上書きも追加もできるのでしょうか?
それとも上書きしたあと、一旦fcloseをして開きなおさなければならないのでしょうか。
よろしくお願いいたします。 >>27
fseek() で書きたい位置に移動して自由に fwrite()/fread() を使うだけで OK です。
fclose() は一番最後に一回だけでいいですよ >>28
どっちのモードで開いてもいいんですね。
また、fopenを2回使う場合も、fcloseは最後の一回だけでいいという訳ですね。
ありがとうございました。 >>27
wは既存ファイルは0バイトに切り詰め、aは出力時はfseekが効かずに常に末尾に追加なので
既存ファイルはr+bで開いて、存在しない場合はw+bで作成するのがいいのではないかな Ruby でやってみた
入力ファイル → 更新後
123456789 → abc456789xyz
filename = "test.dat"
# バイナリ読み書き両用
File.open( filename, "r+b" ) do |io|
io.write( "abc" )
io.seek( 0, IO::SEEK_END ) # ファイルの末尾から
io.write( "xyz" )
end
# 更新後のファイルを読み込む
File.open( filename, "rb" ) do |io|
puts io.read( nil )
end ruby ならきれいに書けるという主張でもないようだけど、誤爆? ム板で最も嫌われてる荒らしの一人。
懸命なruby布教のおかげで、rubyを覚えるとキチガイになるという通説を広めることには成功している。 >>30
>aは出力時はfseekが効かずに常に末尾に追加
これは驚きました!
https://ideone.com/RG43Xw
$ gcc -W -Wall fopen_a_mode.01.c
$ ./a.exe
abcdefgABC
$
https://ideone.com/T8QqyL
$ gcc -W -Wall fopen_a_mode.01.c
$ ./a.exe
ABCdefg
$
新しいことに気が付くようにしていただき、ありがとうございます! まんま教えて貰ったのに「気が付くようにしていただき」なんだな >>38
失礼しちゃいますね!
私が着火したことはほとんどなく、むしろ買ってに周りが発火している、という気がするのですが?
私が着火した、という証拠はありますか?あるというのなら URL で示してください! ruby布教者じゃなくてただのrubyアンチでしょ
布教なんかしてるように見えるの? 定期的に書かないと、その名前すらみんな忘れ去るから x[i][j]でx={0or1}を取る場合、全通りのx[i][j]を生成する方法はありますか? >>43
x[i][j]を使った計算で全通りを比較したいです 誰か質問の意味分かる人いる?
何がしたいのかさっぱり分からん >>45
x[i][j]が変数の関数の最大値を求めたいんですが、全通りの計算をして最大値を求めたいです 全部計算して計算結果を比較して最大値を求めれば良いのでは?
質問の意図が見えない…
iとjの2重ループで全部計算させて結果をresult[i][j]に入れる
その後、もっかい2重ループして最大値を探す
そのまんまだけど… i,jのサイズが2の時x[i][j]の組み合わせは
@x[0][0]=0、x[0][1]=0、x[1][0]=0、x[1][1]=0
Ax[0][0]=0、x[0][1]=0、x[1][0]=0、x[1][1]=1
Bx[0][0]=0、x[0][1]=0、x[1][0]=1、x[1][1]=0
Cx[0][0]=0、x[0][1]=0、x[1][0]=1、x[1][1]=1
Dx[0][0]=0、x[0][1]=1、x[1][0]=0、x[1][1]=0
……って続くと思いますが、この配列の中身の全組み合わせを生成したいです >x[i][j]が変数の関数の最大値
これからして、意味が分からない
xの型や関数の仕様について、ヒントもないのか びっくりするくらいわからんわw
フーリエ変換だとかアフィン変換だとかそういうなんか最重要な情報出し忘れてない? 普通に二重forループ使え。問題文がおかしい。問題がその文章のままなら、たぶん学校か会社を間違えてる。 >>49
@x[0][0]=0、x[0][1]=0、x[1][0]=0、x[1][1]=0
Ax[0][0]=0、x[0][1]=0、x[1][0]=0、x[1][1]=1
Bx[0][0]=0、x[0][1]=0、x[1][0]=1、x[1][1]=0
Cx[0][0]=0、x[0][1]=0、x[1][0]=1、x[1][1]=1
Dx[0][0]=0、x[0][1]=1、x[1][0]=0、x[1][1]=0
ここから値だけ取り出すとこうなる
0000
0001
0010
0011
0100
...
あとは簡単でただの二進数だから1重ループでその整数を1bitずつシフトしてマスクして代入すればいい 何のために二次元にしてるのかイミフ
値も0と1しか入れないなら
もっと簡単な構造にすればいいのに >>49
> ……って続くと思いますが、この配列の中身の全組み合わせを生成したいです
生成すればいい
何が問題なのか説明しないで問題丸投げは嫌がられるぞ
便利な標準関数一つで解決するとかを期待してるなら無理だ bool x[I_NUM][J_NUM]; とすると、x全体で取りうる値のパターン数は
2 ** (I_NUM*J_NUM) になるから、よほど小さな I_NUM, J_NUM でなきゃ
全通りを一度に生成して一覧表で返す方法は無理だよね。
添字 i, j について回る2重ループと、
特定の i, j における x[i][j] に 0, 1 を格納するループ、
合わせて3重のループで「ある場合のx」を生成して
その x で f(x) を計算して、最大値を更新、
3重ループが終わった時点で全パターンでの最大値が得られる、
て感じにするんじゃないかな。
>>46 の「x[i][j]が変数の関数」ってのが、
関数のパラメータとして2次元配列x[][]を取る、って理解だけど。 関数の引数として配列を渡す、って理解?
関数側は、「何それ食い物?」って答えそうだな 組合せ最適化問題でしょ
組合せ変数を0,1で定義してる Cの逆アセ対策の難読化って、ヘッダの関数シグネチャも変えた方がいいの? バイナリを暗号化して復号ローダーつけるとか
クラックするとき一番困るのがこれ >>63
サンクス
復号ローダーは初めて聞いたわw 関数のシグネチャはスタティックリンクすればバイナリには残らない
ダイナミックリンクにするとエクスポートテーブルに載ったりするけどね セキュリティ周りは英語みるしかないね
日本人は忌避感が強すぎる
teratailとかでたまに質問してる人がいるけど
「悪用するひとがいるから回答できない」みたいな発言ばっかり
セキュリティ後進国ニッポン万歳 飲食店の場所取りに自分のカバンやスマホ置く国日本。
敷地の出入り口封鎖にプラスチックチェーン使う国日本。 ポインタ変数のバイト数って32ビット環境が4バイトで64ビット環境が8バイトですか? >>68
そういうのが多いが決まっているわけではない
式sizeof(void*)が生じる値は処理系定義なので
コンパイラのマニュアルに記載されることになっている >>71
コンパイラにより、かつ一定の挙動が保証される
それが処理系定義 >>72
なるほど
ありがとうございましたm(_ _)m ただし実際の実装では>>68のようになってることが多い。
まるで大井川です。 10回に1回くらいsegmentation faultが起こる原因って何だか分かりますか? >>76
宣言した、配列や変数に全部初期値を入れた方が良いということでしょうか? >>78
配列や変数に値を入れるより先に値を読むような処理があるなら、その値は不定になるよ。
不定じゃ困るなら初期化しなければならないし、処理の流れ上読むより先に必ず値を入れることになるなら必ずしも初期化は要らない。 無効な値とかを決めて、全部初期値としてセットしておいたほうがバグは見つけやすくなるかと 全部初期化した方がいいといえばいい、というか…
0とかのデフォ値でいいならそうだよ、というか…
変数に代入し忘れのバグって、変数に代入すべき所でしてないのが原因なワケで
それを直さないとバグったままだよ Cでディクショナリ型のデータ構造が使いたいんだけど何かいい擬似的な仕組みとかないかな 深く考えずそこいらのハッシュのコードをコピペして終わり >>83
tcl/tk
または
memcached/memcache-client 【問題】最大値と最小値を順番に表示するプログラムを作成したい。以下のプログラムに適切なコードを追加して完成させよ。
【プログラム】
int main(void)
{
double a, b, c, max, min;
scanf("%lf", &a);
scanf("%lf", &b);
scanf("%lf", &c);
/* ここにコードを追加 */
if(max<b) {
max = b;
}
if(max<c) {
max = c;
}
if(min>b) {
min = b;
}
if(min>c) {
min = c;
}
printf("%f\n%f\n", max, min);
return 0;
} 【僕の解答】
if(max<a) {
max = a;
}
if(min>a) {
min = a;
}
を追加したのですが、上手くいきません。
どこが間違っているのでしょうか?? 初期化されてないmax,minと比較をしたら結果は不確定になってしまうでしょ
この場合比較自体が不要、代入するだけでいい 宿題か・・・
宿題は宿題用のスレがあるので次回からはそちらへ。 170代目宿題スレッドって2つ生きてるんだ。片方しか見てなかったわ。
両方ともさほど繁盛してないみたいだけど。
最大値、最小値を入力されたデータの一つで仮に設定する手法か。
Cに限らない話だね。アルゴリズムって言うほど大袈裟でもないけど。 >>97
5 年ほど前は大繁盛だったんですけど、最近は授業でも C は取り上げられなくなったんですかね? Ruby では、
a = ARGV[ 0 ].to_f; b = ARGV[ 1 ].to_f; c = ARGV[ 2 ].to_f
# ここにコードを追加
max = a; min = a
max = b if max < b
max = c if max < c
min = b if min > b
min = c if min > c
p min, max 自分ならmax,minに無条件に値を入れないで
if (a < b)
{
min = a;
max = b;
}else{
min = b;
max = a;
}
if (min > c) min = c;
if (max < c) max = c;
にする。 もともと穴埋め問題なのに穴以外のところを変更しちゃダメだろう Makefileを作るのは今もモダンなやり方でしょうか? >>105
モダンな方法は言語によってもいろいろあるようですが(例えばネットに接続してライブラリの最新版を fetch してくるものとか)、でも、私は make から離れなれないですね… 今はninjaだかがモダンらしい
使ったことはないが MPD(Music Player Daemon)のmakeがninjaに変わって、ビルドに泣いた。
mesonというconfigure相当のモノに、configureで指定していたオプションが無くて...
日本語命名品は凶悪だわ。MIRAIとかAnna-senpaiとか。 >>105
C(gcc/cl)でもC++(g++/cl)でもC#(csc)でも現役でmakefile使ってる モダンかと言われると微妙だけど今ならcmakeでMakefile生成でしょ Ruby の、rake, thor みたいな、タスクランナーでも使えば? テキストエディタほどでないにせよ、ビルドツールも喧嘩の種になりそうかな。
大勢の人が集団で開発とか、クロスプラットフォーム向けに配るとかでなきゃ、
好きにすりゃいい気もするのう。
個人的にはmakeが大好きで万能バッチファイル的に使うけど、
俺自身決してモダンボーイじゃないから。 makeってあれサブルーチンみたいなことするにはどうすりゃええの gcc流のオプションをclのオプションに変換してclを呼び出すラッパーある? >>114 本当に単純なサブルーチン呼び出し風なら
サブルーチンに相当するターゲットを順番に依存対象にしてこんな感じ。
.PHONY: main sub1 sub2
main: sub1 sub2
@echo "and now, going main"
sub1:
@echo "this is sub1"
sub2:
@echo "I'm sub2" >>116
おお、なるほど
こんなんでいいのか
助かったよサンクス グローバル変数で、
char A[4], B[4];
と宣言したら、メモリ中でAのすぐ隣にBが来ることは保証されているんですか?
例えば、Aはインデックスが0から3までですが、この範囲を超えてA[4]に
アクセスしたら、それはB[0]にアクセスしたことになるんですか? 環境依存でどっちに配置されるかの保証はなかったような >>120
範囲を超えたアクセスは未定義動作。順序どころか隣接する保証もないよ。 >>120
順序や隣接を保証したいなら struct を使うとか char A[8];
char *const B=&A[4];
でいいじゃんなにが問題なの? >>127
質問者のやりたいことはおそらくそれで事足りるとは思う。
問題があるとすればsizeof(A), sizeof(B)の値が当初の書き方と異なるとかかな。 × 隣接する前提で突破させてアクセスしたい
△ どうも B[0] の値がいつのまにか変わっちゃってるんだけど A[]で突破して書き込んだ可能性をチェックしたほうがいい? 配列操作の関数とかで
void func(int data[], int size){
for(int i = 0; i < size; i++)data[i] = 111;
}
みたいな関数って
void func(int *data, int size){
for(int i = 0; i < size; i++)data[i] = 111;
}
って書いても動くけど、何が違うのですか?
書き方違うだけでまったく同じ? 文法上は違いがなく同じ どっちで書いてもいい
* ではなく [ ] をあえて使って配列ですよと強調することはある IT掲示板群 ttp://x0000.net/forum.aspx?id=15
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン(画像有り)
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
PS malloc / free を実装してみた (C#)
ttp://up.x0000.net/files/TMallocTest.zip どう間違ってもsizeof data == sizeof(int *)にしかならんものなのに
白々しくモロバレな嘘を書くことはあるね、確かに まじめにやると
union{
char A[8];
struct{
char A[4];
char B[4];
}S;
}U; #pragma packや__attribute__((packed))は使わなくてよいの? パディングのせいで上手くいくとは限らない(というが大抵の場合うまくいかない)
ってのは>>125が指摘してるのな >>138
それって言語仕様としてはうまくいくと保障できる? 構造体はメンバの配置順を保証し、共用体は同一アドレスから開始を保証する
charなので境界調整要求が1でパディングに邪魔されることもない charだからといってバイト境界が1になるという保証は無い 隣接するcharの間にパディングされるとしたらどんな場合なの? 俺ってC言語得意だからいっぱい質問してくれると嬉しいな charは絶対1バイトになるよな
それともOSのページングの話 普通にPCで応用ソフト作ってるときにアライメントとか意識したことないわ ここのスレってもしかして組み込み連中が多いのか!? PCは4バイトでやりとりするからint型が一番速いというのは聞いたことがあるが、ソースコードの可読性を落としてまでintで宣言しないだろ
優先順位:可読性>>>>型による実行速度の改善 >>148
4バイト、8バイト、16バイト境界などで配置する処理系があるかもしれない >>158
32ビットCPUなら4バイト、64ビットCPUなら8バイトずつ読む
のがCPUさんにだいたい優しいんよ
ていうかワード境界またぐと例外ぶっこくCPUとかあるし
でもって例外処理で残りを読むとかで超遅くなるとかさー struct は アライメント1/4/8 で半端な部分はパディングする
アライメント4 で宣言順に配置する処理系
struct A1 {
char a[3];
char b[6];
int c;
};
は
a 3バイトの後 1バイトパディングを挟んで
b 6バイト 2バイトパディングを挟んで
c sizeof(int) バイト
こうなる
union の中の struct だけは アライメント1 というのもない
union {
char x[100];
struct A1 a;
} foo;
struct A1 b;
foo.a と b が異なるメモリアクセスになっちまうもの × struct は アライメント1/4/8 で半端な部分はパディングする
アライメント4 で宣言順に配置する処理系
○ struct は アライメント1/4/8 で半端な部分はパディングするという処理系で
アライメント4 配置する場合
言語仕様上
構造体のメンバ間は連続したメモリ空間上にあることは保障してるけど
スキマなく詰めるとかのメンバの詰め方に関する規定は無いんでなかった? 昔コンシューマのセーブデータ解析してたら3バイトづつのデータが並んでて構造体定義に悩んだことあった。 Cユーザーってやっぱ変わった奴多いなー
ガチムチの土方って感じがするわ ボイン多(ポインタ)
なんちゃってガハハハハハハ! >>165
おそらくセーブするときにバイト単位でギチギチに詰め込んでたんだろな。
容量の節約か解析避けの一環か。
ロードしたデータは扱いやすい大きさごとに並べ直して使う。 FAT12 みたいな変態パッキングもあるから、24bit のフィールドなんてマシな方。 8bitCPUなら24bitはごく普通
ファミコンのデータ解析したこと無い? 24bit WAVファイルも3バイトずつ
フルカラーBMPも3バイトずつ >>171
言うほど普通ではないよね
むしろ6bitを無理やり並べるとか もっとケチってたよね >>154
> charは絶対1バイトになるよな
うん、8bitと限らんけどな 確か1オクテットといったら8ビットだが1バイトは8ビットとは限らないんだよな。 おまいらほんとガチムチだな
その才能をもっと色んなジャンルに活かせよ
ゲーム解析するぐらいならCで書かれたPrologのインタプリタのソース読む方が社会的に有意義だし、カッコいいぞ
いいぞPrologは。アルゴリズム特化型言語だ 8進数は、1バイトが6ビットだったことがあってこそなんだろうね おいちゃんの K&Rの表紙は、6ビットの紙テープで描かれた Cという文字だな 今の本?(写真3つ目)は鑽孔テープじゃないのか。
dictionarymay.cocolog-nifty.com/blog/2012/08/c-f754.html 英語では数は3桁区切りだったもんだからつい2進数も3桁毎に区切って考えてしまったのではないかな? 流石にそれは無理があるw
>>181が言うように1バイトと言うか1文字が6bitで良かったから3bit x 2で管理するのが都合が良かった
なので当時のコンピュータには18bitとか36bitマシンとかもあった
その流れで16bitマシンでもパネルとかは3bit区切りになってたりする
https://www.hpmuseum.net/images/2108A-37.jpg ABCDEFを数字として扱うには時代が早すぎたんだよ コンピュータの黎明期は、時間や角度の単位のようにいろんな約数がある方が
応用が効くと思われていたらしい。 >>181
N進数自体は論理的にはNがどんな正の正数でも可能だけど、C言語的に文法上8進数が記述できるのはUNIX系のファイルシステムのパーミッションとかで使いやすいからとかでないかな。 c言語で9ビットのコンピュータ使ったことあるが、頭が狂いそうになったよ これまで常識だと思っていたことをあっさり否定されてしまうから? >>191
そういう特殊な環境だとむしろアセンブラを使いたいな。
Cじゃ活用できないアーキテクチャになってそう。 組み込みだと4bitマイコンあたりはまだ現役で使われてそうだな
C言語処理系があるかどうかは知らんけど >>194
Cがあったとしても char の最少サイズは 8bit が保証されてるから、Cを使うとかえって面倒そう。 >>192
0xffが255、0x1ffが-1になる
これだけで充分パニック アセンブラで別のCPU勉強し直すと変に前のCPUの知識が足引っ張って戸惑う。
Z80 → x86
セグメント?概念は理解できた。記述方法よくわからん。
repって何?
byte prt ? word ptr? あ、データサイズ指定必要なんだ。
→とあるスパコンCPU
え?オペランド3つ?
あ、0レジスタは聞いたことある。
スタックレジタ無し?汎用レジスタで代用? こんなまとめ記事のようなものを発見した。
1バイトが8bitに定まったのは2008年 - Qiita
https://qiita.com/yaju/items/c5da6df2221d5c3611e0 ソフト的に1バイトは8ビットかも知れないが、回路的には奇数アドレスは存在しないから、1バイトは16ビットなり32ビットで扱われているんだよな > 回路的には奇数アドレスは存在しない
そんなものはマイコンのアドレスバスの接続方法による
小容量の内蔵RAMしか利用できないマイコンだと16bit単位とか効率悪すぎるだろ >>205
データバスが16ビットのデバイスはA0が存在しないから、奇数アドレスがないんだよ
ハードウェア的には8ビットは扱えない
上位はコンパイラーが無視してるんだろ
昔の6800系のgccは奇数アドレスが使えなかった 8ビットバスとかダイナミックバスサイジングとか無視して何言ってんの。 8ビットが扱えるやつのint型もエンディアンがビックかリトルかで、ややこしくなる場合がある >>189
> N進数自体は論理的にはNがどんな正の正数でも可能だけど
N = 1 でやってみ >>211
1倍すると桁が増えないといけないからいろいろ破綻しそうだな >>219
その1進法に対応する2進法はこんな感じ
つまり違うもの
0
1
00
01
10
11
000
001
010
011
100
101
110
111
0000 >>221 上手い書き換えだな。
何やら見覚えのある「位取り」というか「桁上がり」法だと思ったら、
「連番を(数字でなく)英文字を使って表現する」やり方がこれだ。
1番 a
2番 b
...
26番 z
27番 aa (位取り/桁上がりの 0 に相当する記号が存在しないため)
28番 ab
...
『Cの宝箱』(工学社)って本で数値からの変換プログラムを含めて初めて見た。
ANSI以前の古い本だけど、扱ってるネタは今でもなかなか面白い。 1進数のかけ算
111 × 11 = 111111
1111 × 11111 = 11111111111111111111 >>215, >>219
それ桁数でカウントしてるだけでN進数と言うのは無理あるだろ 定義上は間違ってない
0の桁上がりが00で次が000なら成立してる >>226 確かに「Excelのカラム」がこれだね。
範囲指定の時にマウスポインタを暴走させるとちょくちょく目にする。
身近な実例なのに思いつかなかった。
それにしてもワッチョイの英数部分(何て呼ぶんだろ?)が FF11 とは。 今このスレ見返してたんですが
gcc -W -Wall
って意味あるんですか? -Wallオプションだけと何か違うの? >>232
私も gcc/clang でそのオプションを好んでいます、理由はしりません… man gcc を見ると -Wextra のところに This option used to be called -W.
と出てるね。日本語だと「かつては -W と呼ばれていた」で合ってるだろうか。
-W を指定することと -Wextra を指定することは同じ効果かな。 clやgccのassertって生真面目にabortしてうざいね
イベント1001なんか記録してくれなくていいのに 元気があればなんでもできる。
Cさえ出来ればなんでもできる。 C書いてる人ってみんな可変長配列とかリストとか木構造とかグラフとか自前で書けるよな? >>240
プロのミュージシャンは「蛙の歌」くらい自分で弾けるよな? くらいのシュールな質問だ 職業画家ならピカソのイタズラガキぐらい描けるよな? 単なるそういう構造でも感心するような実装ができたらすごいけどな。
メモリ管理は奥が深いよ。 名前が付いてるようなのは既存のを使えば良い
付いてないような複雑な構成、特殊な構成のものがさらっと作れるようになって一人前
名前が付いてる構造をただ列挙して喜んでるようなのは初心者 カーニハンが引用して有名になったフレーズだったと思うけど
「職業プログラマーでも二分探索を正しく実装できる者は意外なほど少ない」
ってのと似てる感じね。
出典はベントリーさんの記事だったかな。
で、ベントリーさんが出してる二分探索ルーチンの例が
(細かいこと言えば)誤ってるというお見事なオチ。 いかん、カーニハンさんに「さん」付けるの忘れた。
カーニハンに「さん」を付けるとなんか座りが悪い気がするんだよ。
べつに「ハン」は関西弁の「〜はん」じゃないのだけど。 インブリードチェックとかねー
掘り掘りの打ち切り確認とか
可変配列で返せると効率的なのに記述や関数使用方法がCでは面倒くさいという
web上のサラブレッド血統表のインブリードどこも結構いい加減な自動抽出だし >>254
そこは俺の投稿はアカデミックじゃなくて井戸端の噂話くらいなモンってことで。
何なら便所の壁に描かれた傘差したネズミの落書きでもいいのだが。 >>252
正しく実装ってのが何を指してるのかよく分からないけど、その解説ってどこかにある? 2ch (5ch) ではカーニハンは蟹飯とか呼ばれたりするのも普通だからなー。
さんを付けた方がすわりが良いと思うなら付けてもいいが、
ここでは雑に言っても文句は出ないよ。
敬称を付けなきゃ敬意がないってわけでもないし。 >>258 の人に質問されたのでちょこっと書庫をひっくり返してみた。
書籍資料しか示せないし、古い本だから見つけるのは大変かも知れんけど。
今回は「さん」無しで書かせてもらう。人名が多くてやかましくなるでな。
カーニハンによる言及は『プログラミング作法』(ASCII)の第2章。
見直して気づいたけどベントリーからの直接の引用ではなかった。
あと、この本はカーニハンとパイクの共著だったので訂正させてもらう。
ベントリーによる2分探索法は『プログラム設計の着想』(近代科学社)の第4章。
ここに「ベル研とIBMで試したら2時間かけて正しく書けたのは10%」と出てる。
この章をまるまる使って、二分探索ルーチンを題材に、正しいプログラムを書く
手順を説明してるが、使用言語は擬似コードとBASICの方言。
補足としてネット情報 Wikipedia 「二分探索」ページ
特に「実装上の間違い」の部分が興味深いかと。 >>261
丁寧にありがとう。
確かにやらかしてたわw 見てみたけど...
アルゴリズムの問題じゃなくて
ただのインデックスのオーバーフローか
インデックスが計算途中でオーバーフローする心配をするなら
要素数自体がintの範囲を越える心配やメモリ不足の心配もしないと intじゃ足りないかもしれないから
size_tじゃないとバグとか言い出すのか
くだらん 斜辺を求めるコードも
sqrt(a*a+b*b)
なんて書いたらバグだと言われちゃうね まあ、ビット数の少ないCPUを使ってた頃はオーバーフローで実際にバグの挙動を示していたこともあったのかもね。
64bitになって、今しばらくはインデックスの足し算をいい加減な順番で行ってもオーバーフローになるほど実メモリが積めなそうだけども。 >>265
aとbがintなのにキャストしないタコいたら許さん >>263
だからアルゴリズムじゃなくて実装の問題だって話なんだろ。
そして型が int だとか size_t だとかの問題でもない。
どんな型であろうと計算の途中でその型をオーバーフローする可能性がある式だというのが問題であり、扱ってるデータではオーバーフローしないことを意識した上でそういう式を選んでるのかたまたまそういう条件になってるのかは大違いってこと。
最近は64bitだからいちいちそんなこと考える必要もないというなら、それは違うだろと(検索対象がメモリで64bitに及ばないメモリ量の環境でしか使わないコードだという考慮くらいは必要)。
特にライブラリなんかでは、インデックスの許容範囲がその型の許容範囲より狭いならば明記しなければならない。 >>268
>>265もバグという主張だね?
>>267
a, b はdoubleとする 単純な数値計算も簡単じゃなくなるね
大変だ
>>268
底辺a, 高さbの三角形の面積を返す関数を書いてみて >>269
扱う値の範囲をなんの考慮もせずに書いたコードがたまたま動いてるならバグと言うかはともかく考慮漏れだわな。
巨大な空間で距離を計算する話だったら、とりあえず式が double で足りるかくらい考えるだろ?
>>270
オーバーフロー回避を意識する必要があるなら a / 2 * b とか?
整数型なら a / 2 * b + a & 1 かな?
扱う値によって型なり式なりを選べってことだよ。 >>271
a & 1 にカッコ忘れてるのは多目に見て >>271
三角形の整数の計算式は全然ダメね。
書き直す気も無いけど、値の範囲に適用する式と型の考慮が必要ってのが言いたいことね。 ビットand の & の優先順位が低いのがすげー気になるマン a,bがdoubleでsqrt(a*a+b*b)以外にどう書けと >>278
もし double でも計算途中でオーバーフローする可能性があるなら、最初に適当な係数の平方で a b を割って計算してから係数を掛けるとか?
あるいは long double が使えるなら単純にそれで計算するとか。
逆に言えば、オーバーフローする可能性があるならなんとかしないといけないわけだから、なんの変形もせずオーバーフローするに任せたらそれこそバグでしょうよ。 >>279
また嘘言った
後で a b 共に2乗するんだから係数の平方じゃなくて係数そのもので割るんだね。
すまん doubleでオーバーフローって、10の何乗を想定してる? それオーバーフローじゃないし、
情報落ちのことだとすればsqrt(a*a+b*b)をどう工夫して防げと? >>281
1.79769e+308
まさか、これを知らねえんじゃねえよな で、宇宙の観測可能な距離をヨクトメートル単位で表したら? デカルト距離は物理的な空間でしか使われないわけじゃないしなあ(屁理屈 64bitあれば大きいほうはエクサ、小さい方はアトまで扱える
今飲んでるコーヒーの液面からカップの底までが1アトパーセクくらい >>282
aに対してbがはるかに小さいとして
sqrt(a*a+b*b)がaになってもあまり困らない double で何やったらオーバーフローするのかってことじゃなく、必要な対象を計算するのに必要な型や計算手順は何かってことだろ。
掛け算や指数を扱うならオーバーフローについては普通に考慮するもんだと思うけど、そうじゃないのか?
今扱おうとしてる対象について考慮してるから double なら大丈夫だと考えてるんだろ。
で二分木については足し算がオーバーフローする可能性が盲点ってことで、なるほどと思うべき所だろ。
アルゴリズム上も計算途中に最初に与えた imax を超える値が現れるようには見えないんだから。
今時 double も 64bit整数も当たり前だったとしても、SIMD使いたいからデータ長を抑えたいなんてこともあるでしょ。 一般論で答えても叩かれる
質問内容に特化して答えても叩かれる
どうしろと 俺くらいになればケッセルランを12パーセクで飛ぶくらい余裕 >>289
通常使わない範囲の心配を無条件で(コストをかけてでも)するべき
なんて主張はあほ
その例が>>265 >>278
いくらでも方法がある
ldexp / frexp を使うのが普通かな >>240
みんなかどうかは知らんがおれは書けるな int x=0;
int y=(x=1)+(x=2);
とするとyが4になってしまいます。
3だと思うのですが。 >>271
>オーバーフロー回避を意識する必要があるなら a / 2 * b とか?
それは回避したことになりません、演算子 / 2 と * b のどちらが先に処理されるかはコンパイラが籤引きで決めるか独断偏見で決め打ちするのでは? >>296
副作用は副作用完了点までのどこかで起こることになっているのでそういうこともある。
っていうか普通は警告が出るでしょ。 int x=0;
x=1;
x=2;
int y=x+x; //(2+2)
という話になっているのだと思われ あとは優しいおじい・・紳士様がアセンブラでは実際どうなっているかを解説してくれるはず >>297
自信を持っては言えないけど、/ 2 してから * b するのとその逆とでは結果が違うんだから、書いた式と結果が異なる可能性がある計算順にコンパイラがいじるものかね?
例えば各項を関数として a() / c() * b() にした場合、a 〜 c がどの順で実行されるか、つまり項の評価順は保証されないけどそれら結果を使った計算順は式通りになるんじゃないの?
でももし仮にそういう懸念があるなら、カッコ付けるなりそれでだめなら2手に分けるなりすればいいんじゃね。 >>302
アセンブラだとxに2入れて、yに4入れて、おしまいだろうな。 誰も逆汗しないのな。
一昔前だったら
A「俺がやってみるから待ってろ。」
B「いや、俺がやるから(ry」
C「いやいや、俺こそが」
AB「「どうぞどうぞ」」
の前振りだったのに。
VC++2019のデバッグモード
int y = (x = 1) + (x = 2);
00C118FF mov dword ptr [x],1
00C11906 mov dword ptr [x],2
00C1190D mov eax,dword ptr [x]
00C11910 add eax,dword ptr [x]
00C11913 mov dword ptr [y],eax
最適化したら 304 になるんだろうけど。 >>297
/ と * の優先順位は等しくて左結合なんだから疑問の余地はない。
a/2*b と書いてあったら a を 2 で割ってからそれに b をかける。
またはそうしたかのように見えるような振舞いをすることは保証される。
そうなってなかったらコンパイラのバグだよ。 例えばスケーリングなんかの時、オーバーフローを避けるため割り算やってから掛け算することもあるし、丸め誤差を小さくするため掛け算やってから割り算することもあるし、
意図して式書いてるんだから順序を勝手に変えられたらやっぱり大問題だよな。 >>297
オーバーフローは回避出来てるが
かわりにアンダーフローの可能性が出てくる
だから>>271はバグ >>311
ありがとうございます、たしかに副作用完了点に対する私の誤解です
@値の評価の問題、と、A副作用の問題、とを完全にごった煮にしてました、今回は副作用は関係ない…
>QZがここまでアホだとは
現在までの推移を客観的に観察している限りにおいて、これはスランプでは済まず、私はこれからもっと阿呆になっていくのだろうと私は予測しています
https://mevius.5ch.net/test/read.cgi/tech/1434079972/ へのエントリー数もパッタリ止まってもう増えそうもありません アホが使うと使い手とそっくりな動きになる
Cとはそういうものだ >>314
行を分けると何が解決するって?
お前もQZと同じアホ? >>309
>>268によると
オーバーフローも丸め誤差増大も
両方回避しないとバグらしいぞ オーバーフローを最近勉強して
それだけが気になって
それを回避するために別の問題を起こす
初心者君のたわごとだから
放置すればいいんだけど どんくらいまでの誤差を許容すべきかは
なかなか数学的な考えどころ 許容誤差
パラメーターの対応範囲
コスト
保守性、可読性、...
これらを総合的に考えてコードを作るのが普通
1個だけの要素が気になるといびつな実装になる
色々な規格も偏った視野で作られる事が多くて
いびつな物が多い
それぞれの項目を勉強するのはもちろん良いこと >>317
両方起こりえる状況なら変数の精度不足というバグか。 >>316
ああアホには「文」を分けると書かないとわからんかw 文を分けると何が解決するって?
乗算と除算の演算順がコンパイラによって変わる
というのはQZの勘違いな主張で
明確に順番は決まってる
(QZが>>312で勘違いを認めている) オーバーフローの話は (imax + imin) / 2 ではなく imin + (imax - imin) 2 と書けば回避できるってのが発端なわけだけど、何がそんなに気にくわないんだ?
盲点とも言えるよくやりがちなことなんだから、素直に吸収しときゃいいんじゃないの? >>324
オーバーフローの可能性があるならそうやって回避可能
っていうだけの話なのに
パラメーターの型全ての値に対応出来ないとバグ
とか言い出す人がいるから あぁ、もしかして >>268 のことか?
んじゃ int の代わりに size_t だったら >>324 の前者の式のままでもいいってのがお前の主張か。 元はカーニハンとかいう人だろ
その影響を受けたのが>>268
オーバーフローの可能性が無いなら
前者のままでも良いっていうか
前者の方が良い場合もある
コストは確実に前者の方が安い
リニア検索ではなくてコードサイズの大きな2分検索を使うあたり
パフォーマンスが全くどうでも良い所ではないということもわかるわけで
移植性は後者、コストは前者、
可読性は微妙だが前者?
intよりsize_tを使うべきなんて思ってないよ
使う範囲、使う環境、移植性、...
などなどでどうするべきかは変わる >>328
お前が揶揄してる人(おれ)が言ってることがようするに
> 使う範囲、使う環境、移植性、...
を考慮して選択しろと言ってるんだが。 C言語スレだから
チープな8bit環境から
スーパーコンピューターまで
様々な所で使われる
重視すべき項目は時と場合で大きく違う >>327を見ると
常に後者を選ぶべき
だと思ってるように見えるけど >>268 の次の >>271 なんかを含め流れを見て言ってくれてるのかしら >>265 も
オーバーフローやアンダーフローを意識してコーティングすべきと
それは良い心がけで >>333
たぶん論旨は伝わったと思うので追い打ちかけるつもりではないが、レス付けるに当たっては「オーバーフローを回避するなら」と必ず付けてるし、扱う値の範囲を鑑みて型が充分か考慮しろと言ってるだけのことな。
扱うのが宇宙の座標をメートル単位で、くらいの話なら double でもオーバーフロー的な問題は無いなとか、
でももしシミュレーションで宇宙を100次元空間として体積を求める話だったら double でも大丈夫かな?とか考慮するでしょ。
まあそんなケースだと値の大きさより有効桁の方が心配だけど、なんにしてもとりあえずデカい型だから大丈夫wなんて漫然と思ってるならただのアホという至極当然の話。 >>323
> 乗算と除算の演算順がコンパイラによって変わる
> というのはQZの勘違いな主張で
> 明確に順番は決まってる
エビデンス持って来てからほざけ >>334
状況によって適切なコードを選ぶべきと思ってるなら別にいい
そうじゃなさそうだったので
「間違ってる」「バグ」「正しくない」という主張じゃなかった?
2分検索が10%しか正しく書けないなんてことはないと思うんだがね >>336
>2分検索が10%しか正しく書けないなんてことはないと思うんだがね
そう、ここが気になったんだけど、でももし二分検索を書いたこと無い人がアルゴリズムを見て一発で動作するコードが書けるか?という話なら、案外その程度かもと思ったり。
分割時の端数処理の考慮が不適切でインデックスが変化せず無限ループに陥ったり、検索から抜け落ちる要素が出たり、要素数が0〜2ないし3くらいの範囲でうまく動かなかったり。
ちょっと動かせばすぐ修正点に気付いて動くコードに仕立てられるだろうけど、ぶっつけで動かせるかと言ったら案外難しいんじゃね。 クイックソートを一発で書けと言われるとちょっとつらい。
あまりにうろ覚えすぎる。
30分待ってやる
と言われれば思い出しながら余裕を持って書ける。かな?
いやどうだろう?
ソートは完璧だろうけど、アルゴリズムはあやしいな
「クイックに似た何かソート」になりそうかも >>296,298-301
些細なことですが、>>296,298,299 の結果は納得いかないです
>int y = (x = 1) + (x = 2);
たしかに gcc/clang とも警告は出ますが、しかしそれはシーケンスポイント間で i を複数回書き込んでいる、という警告で、それは i の値が 2, 5 のいずれかになるか不確定という意味ですね
しかし演算子 + のオペランドの値は確定していて、すなわち 2 と 5
だから y の値は、この場合は確定的に 7 になるはずです
実際、手元の clang(8,0,1) でコンパイルした場合、結果は y = 7 で上の解釈と合致します。
私は gcc がバグっていると思いました。 >>339
×シーケンスポイント間で i を複数回書き込んでいる、という警告で、それは i の値が 2, 5 のいずれかになるか不確定
○シーケンスポイント間で x を複数回書き込んでいる、という警告で、それは x の値が 2, 5 のいずれかになるか不確定 既出かもしれんが
>int y = (x = 1) + (x = 2);
演算順は
(x = 1)
(x = 2)
左辺値 x + 左辺値 x
y = その結果
なんじゃないの? >>339
なんだか >>340 だけではなくて、いろいろ間違えまくってますね…ごめんなさい、今日は寝ます >>341 ありがとうございます
JISX0301 の代入演算子をみると
>「6.5.16 セマンティクス「代入式は、代入後の左オペランドの値を持つが、左辺値でない」
つまり
式 x = 2
の値は 2 ではなく x というわけですか…なるほど 式の値は x = 1 なら 1 だけど、その式の値が x と同一といわれると微妙な気が
コンパイラによって結果が変わってきそうな気も >>347
PASCALが嫌いな人が作った言語でか? 代入も比較も同じ = 記号なんだけど代入した結果を利用できない言語はあるね。 代入式なら
a = b = 0:
は大丈夫だけど、
代入文の言語ではダメ(文法エラー)
卑近な例だと excelVBAとか あ、そうだ。昔の BASIC がそれだったな。今もそうか。 >>359
C言語以前の言語はたいてい駄目だな
例外はLispぐらいかな ま、しかし、本当なら代入は全く違う記号(あるいはワード)使って欲しいところではある。
昔々中学生の頃に初めてBASICのリストを見て A = A + 1 ってなんじゃこりゃと思った事あるし。
普通の数学や算数とルールが違っているのに同じであるかのような記号の使い回しで混乱w それ小学生のとき見たからすんなり入ってきた
方程式とは違うよってご丁寧に書いてあったし混乱はなかった >a = b = 0:
BASICじゃ
bが0なら a=-1
bが0でないなら a=0
だっけ。 そっか、そのとき b = 0 は代入文じゃなくて、値を持つ比較式ですね
文法は間違いでした =は代入が比較より使用頻度が高いので、2文字(=:)が代入だと地味に面倒そう。 変数名を文字列で取得したいんだけど どうしたらいいかな
printfデバッグとかで、 printf("hogehoge=%d\n",hogehoge); ってやるじゃん?
これをちょっとだけ効率よくしたいけど、マクロでどうにかならん? >>371
マクロ定義のときは識別子に # を付けると識別子を文字列扱いできる。 #define POUT(x) printf("%s = %d\n", #x, (x))
こんな感じ? #define POUT(x) printf(#x " = %d\n", (x))
こっちの方がいいか? 文字列リテラルの連結は滅多に使わないけど盲点というか
わかってて使うには良いものだね
"aaaa" "bbbb" → "aaaabbbb" として解釈される >>375
よく使ってました
長い文字列を記述する際に
空白文字ではなく改行文字を入れてたな >>374
書式文字列が常に同じになるケース(>>373)だとコンパイラの最適化で使い回されるようになるけど、
変数名を連結して書式文字列が場所ごとに変わっちゃうと使い回しが効かなくなるから、メモリ使用量とかファイルサイズで不利になるかもね。
前者にしても変数名そのものの文字列は別途定義されるのもあってほんの些細な違いだから、しいて言えばって程度の話だけど。 and が & と &&
or が | と ||
という具合に bit 演算用と論理演算用で演算子が違いますが
bit 演算の xor は ^ で
int a = 123, b = 456;
のとき a^b と描けますが
論理式の xor はどう描けばいい?
bool u = true, v = true;
のとき u^v と描いても問題無いですか? bool に 0 と !0 以外が入ってても大丈夫ですか? もし御存じの方がいらっしゃったらで良いのですが
"u ^^ v" みたいな演算子が無い理由も知りたいです
問題後出しで済みません ビットごとのxorは暗号とかで多用するけど、
論理式のxor(一方のみ真)はめったに使わないからかと。
!u != !v が最小かな。 関係演算子の結果はint型の1か0なんだから
a < 124 ^ b < 456 でもいいはず C99以降のbool型(_Bool型)の値はfalse(0)とtrue(1)のどちらかしか取り得ない
変数や式の評価が0以外の場合はすべて1に変換される
評価結果の値が不明の場合はbool型にキャストすると良い
(bool)u != (bool)v イディオムとしては !! を付ける (否定を二回やる) というのもよく知られている。
(見づらいので良くないという意見もある。) !!は厨二病臭くて俺はあんまりやらないが
この程度で読みづらいとか言い出すスキル不足なやつに迎合する意図は毛頭ない 0, !0 意外の値が入ってた場合にどんな結果を期待するかによる >>395
話の流れぐらい読めよ…
>>385が成立するかどうかだろ C言語に使ってるエディタとかIDEとか教えてください
OSとかの環境もあるとありがたい >>398
C言語を何に使うかによって全然違うと思うけど >>398
コンパイラ:cygwin の中の mingw32
エディタ:xyzzy
あと cygwin の make 学習用途で ideone や codepad 規模で済むなら Webブラウザ >>398
VisualStudioCodeの統合ターミナルでWindows10のWSL2利用
参考として>>394の環境は以下の通り
https://i.imgur.com/uDwONkZ.png >>398
OS: Windows10
コンパイラ: gcc と clang (msys2 の pacman で入るやつ)
その他に Open Watcom C とか LCC (LSI-C じゃなくて Little C Compiler ね) とか
エディタ: Emacs 初学の時、H8に書くとき、arduinoに書くとき、それぞれ全部違ったわ。 >>398
OS:Linux(Fedora32)
コンパイラ:gcc
エディタ:vim 漏れは、Windows 10, WSL, Ubuntu 18.04 で、
VSCode の拡張機能、Remote WSL も使う
Linux側には、日本人が作った、バージョンマネージャーのanyenv で、rbenv, nodenv を使って、
ruby 2.6.6, node 12.16.2 を、build-essential で、コンパイルして入れた
yarn は、Windows側に入れて、WSL から、拡張子なしのyarn コマンドを呼べる。
これは、#!/bin/sh で始まるシェルスクリプト
anyenv は多言語向きで、rbenv, nodenv, pyenv, phpenv などを同じ使い方で、統一的に扱える
build-essential には、
gcc(GNU C compiler), g++(GNU C++ compiler), libc6-dev(GNU C Library), make などが入っています
パッケージ: build-essential
https://packages.ubuntu.com/ja/bionic/build-essential build-essential以外はC言語には関係ないな Cに限らず汎用で使える開発環境で色々やってるってことかと。
俺も基本的にはvimとmakeで何でもやる。
vimの中でとりあえず :make と打ってQuickFix機能でエラー修正。
上手く拾ってくれない時は ~/.vimrc で errorformat 変数に追加。
>>398 の人はOSも知りたいってことなので追加。
Linuxのウィンドウ環境使わないコンソールでfbterm(日本語表示用)。
ツール類はディストリビューションに入ってた奴。 int main (void)
{ char a[256];
printf("Enter a string:");
scanf("%s", a);
(以下略)
勉強中に上のような「キーボード入力からchar型配列に文字列を格納する」という処理を見かけました
この例だと(ヌル文字含め)256文字以上の文字が入力されたときはその後の処理が正常にできなくなりますよね
現実的には値を充分大きく指定しておけば問題はないのでしょうが、入力された文字数に応じて要素数を適切に設定したりはできないのでしょうか? >>414
出来るけど、そのレベルの初心者にきちんとしたやり方を説明するのは難しいので
とりあえず入門書を最後まで読んでからにして。 >>414
scanf("%255s", a);
とか書いとけばいーんだよ こんなもん
scanf使うなとか言うアマチュアは脳死 scanfは入力ミスでへんな無限ループに陥ったことがあるからなぁ。 scanfの問題ではないね
!=EOFなんて書くバカが100%悪い 入力バッファに残った改行コードが問題の場合は fflush(stdin) で吐き出さないとどうにもならない fflush() が確実に効くのは出力ストリームだけでしょ。
stdin でも使える独自拡張された環境もあるか知れんけど。 scanf前にバッファクリアするコードあったけど、
そういうやつってパイプやリダイレクトつかっても正常作動するの? パイプやリダイレクトか判定する方法がOSによって提供されてる環境なら問題ない 方法が用意されててもそれをきちんと利用してるソフトが少なかったら意味ないぞ。 scanfをそのまま不特定多数が使うソフトに入れることなんかないんだから
正しく入力してください
で終わる scanfを何に使うかという話と
仕様を理解して使うという話は
別問題だ >>416
scanf("%*s", 255, a);
みたいなのなかったっけ
うろ覚え 引き数から引っ張ってくる * がないとなると
sprintf で scanf フォーマット文字列を作るということになる?のか? >>432
scanf の * 書式指定子は「読み捨て」の指示だったね。
printf の * とは使い方が違うけど、ちゃんとある。
…存在をすっかり忘れてたよ。ありがとう。
>>433
カーニハン&パイクの『プログラミング作法』には
sprintfで書式指定文字列を作る方法が載ってるね。
下に示す例に比べれば手軽で分かりやすい。
入力文字幅がコンパイル時固定ならマクロを駆使して…
// マクロ名を「マクロの内容を表す文字列」に変換するマクロ関数
#define MACRO_TO_STR_SUB(name) #name
#define MACRO_TO_STR(name) MACRO_TO_STR_SUB(name)
#define WIDTH 15 // 入力制限字数(末尾の'\0'を含まない)
char buf[WIDTH+1]; // +1 for '\0'
scanf("%" MACRO_TO_STR(WIDTH) "s", buf);
こんな感じにできるけど、面倒でしょ。 char fmt[(size_t)floor(log10(~(size_t)0) + 1) + 3];
char buf[256];
sprintf(fmt, "%%%llus", sizeof buf - 1);
scanf(fmt, buf); >>435
scanf("%" #WIDTH "s", buf);
じゃだめなんですか? #define MACRO_TO_STR(name) #name
そもそもこれもだめなんですね 後でメンテが大変だぞ
半年経ったら、今の自分が他人になる IT掲示板群 ttp://x0000.net/forum.aspx?id=15
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン(画像有り)
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
☆ VMを書いた(C#) * x86ではない!
ttp://up.x0000.net/files/TSimulang.zip
☆ malloc / free を実装してみた (C#)
ttp://up.x0000.net/files/TMallocTest.zip #define WIDTH 10
#define MACRO_TO_STR(name) #name
MACRO_TO_STR(WIDTH)
は渡された識別子をそのまま文字列化するので "WIDTH" になる
マクロWIDTHを展開した後での文字 "10" が欲しいときは >>435 のように
一見無駄に見えるマクロのピンポンを行なう >>428
その「正しく入力してください」に至らないのが今回の話題 >>446
ん?
コードで表示しろって言ってるんじゃない
クレームが来たらその人に対して言えってこと
つまり
不正入力時の動作は不定がソフトの仕様
で問題ないだろってこと 不正入力ではなくてコンソールと入力バッファの仕様が問題
標準入力stdinがキーボードの場合入力バッファには目的とする文字コードの直後に必ず改行コードが残る
scanfの書式が%dなどの数値型だと改行は取り込まれないので数値型を連続して使用した場合は型が合わずに続くデータを取りこぼす >>449
正しい入力で正しく動かないならそれはバグだよ 訂正
たしかに数値型だけなら問題はないね
数値型と文字型の混在時に問題が起きる
scanf("%d", &x); // 数値 + 改行
...
scanf("%c", &y); // 必ず直前の改行となるので入力不可
...
scanf("%d", &z); // 数値 + 改行 無理にscanf使わずに
fgetsとsscanfやろ Windows10proでC使いたいんです。
目的は大量のテキストデータの変換なので、
グラフィックとか音とかはプログラミングしません。
テキストでコーディングして、
CUIで実行ってな感じができればいいんですけど、
このぐらいだとMinGWが適当なんでしょうか? >>453
プログラミングの教育現場では、未だにscanf()が使われているんだ
この関数の欠陥部分も含めて教育の題材にはいいんじゃないかな >>454
>>453は正しいだろ
>>458
対策しようのない欠陥だから唯一できる教育は「使うな」しかないけどね 初心者教育でとりあえずコードを書い動かしてみる
でscanfじゃなきゃ何を使えって? >>460
対策しようのない欠陥と自分で言いながら何が正しいとぬかす? 配列もFILE構造体も教えてない時点でfgetsとsscanfとか無理だろ
逆にこの辺まで教えてまだ実用的な入力関数が作れないようなら教え方が下手すぎ つーか、その被害者がいつまでもfgetsとsscanfにしがみついたまま進歩しないんだろうが >>462
対策しようがないから使わず他の関数使う
って話なんだが、理解できないのか?w >>467
fscanfとsscanfにしがみついてるのはお前
俺はそんなアホなことしてない scanf要らねと思ったら後はgetcharで何でも出来るだろ >>468
ならいいじゃん
お前以下の奴なんてめったにいないんだしw >>470
罵倒だけのレスもらうと優越感で気持ちいいわ 罵倒だけの>>468みたいなレスを見ても別に優越感なんて感じないけどね
むしろ憐れみしか感じないw >>473
まあいいからfgetsとsscanfにしがみついてろよ
俺がどうかしてやる筋合いないし勝手にしな ここ技術板だぜ? 少なくとも何らか専門用語入れようや > 罵倒だけのレスもらうと優越感で気持ちいいわ
どこに専門用語があるんだろう…?
ますます哀れに思えてきたわw 技術的な話で突っ込めなくなってる無様な姿が最高の褒め言葉さ fgetsとsscanfを使うのが正しい!と強弁してるだけで説得力ねえんだよ >>478
scanf使うならfgetsとsscanf使えって話が出ただけでないの? scanfの使い方の話をしてたんだよ
そこへ付いて来れないからって他の関数を使えと話を逸らしに来たやつがいて
アホつったら何の説明もなしにfgetsとsscanfを使うのが正しいと強弁する別のアホが来た 464あたりでscanfを使う理由をちゃんと説明しているのに
そこは無視してくだらねえ戯れ言ばかりぬかしやがる だから何の説明もなしにdisっても説得力ねえんだってば scanf使いたいなら割り切って使うか、それで起こる問題を解決したいなら別の関数使えって流れじゃないの?
モメるポイントが分からんのだが。 >>414 の質問に戻ると getchar あたりで1字ずつ拾いながら
必要に応じてバッファを拡張する方法になるのかねぇ。
%s の機能だけなら空白と空白以外だけ考慮すりゃいいわけで。
ロケールまで対応させるとこれまた大変そうだけど。 >>485
入力した文字列を何に使うのか次第だろう。
入力すること自体は手段であって目的ではないのだから。
オンメモリに全部展開しないといけない用途なのか?
ハッシュを求めるために計算済みの値は捨てていいのか?
暗号化のために一定のブロック長があればいいのか?
適した方法はそれぞれ異なる。
んでその当初の質問の答えは既に出てるし。 「getchar あたりで1字ずつ拾いながら」
ってことを経た後でないと scanf を正しく使うのは難しいんじゃないかな。 >>480
>scanfの使い方の話をしてたんだよ
>そこへ付いて来れないからって他の関数を使えと話を逸らしに来たやつがいて
>アホつったら何の説明もなしにfgetsとsscanfを使うのが正しいと強弁する別のアホが来た
ここだけ読むと >>480 がただのアスペでコミュ障にしかみえない >>488
実際そうかなと思うよ。他の人の話の興味が移ってきてるのにじずんの言いたいことが正しい 途中で書き込んでしまった。
自分の言いたいことが正しい、他のことを話す奴は理会できてないって思考なんだろう。 めんどくせえから GNU のライブラリにある getline() でも使っとけよ。
1行がどんなに長くてもメモリが許す限りどんどん読んでくれるぞ。 関数を呼び出す側が、使用するメモリの上限をコントロールできないというのは
それはそれで微妙にリスク 誰にも迷惑かからないところでどう使おうかは自由だな。 >>488
ここは技術板だ
アスペの話がしたいカナーはメンヘル板か医者板へ逝け >>495
scanf の使い方の話は終わってね?
議論したい点として何が残ってるの? >>496
あんたに何の権限があってそんな命令するんだよ
余計な口だしはしないでもらおうか getchar()からが良い
scanf()は反面教師 >>499
人の話を完全に無視して同じことばかり呟き続けやがって
ほら、どでかいブーメラン返してやんよ
> アスペでコミュ障 >>498
入門書のプログラムは基本的に使うのは読者本人だから、お手軽な入力処理として使うのはありだと思う。ただ、使い方の注意点は簡単に補足しておいてほしいかな。知らずに、固まった!バグだ!とか騒いだりしないように。
それと、入門書の時点で堅牢な入力処理なんて必要ではないけど、将来的に実用的なプログラムを作るときには必要になってくるということを触れておいてほしい。 >>500
ほんこれ
連中はこの指摘に答えられない
だからレスがない IT掲示板群 ttp://x0000.net/forum.aspx?id=15
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン(画像有り)
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
☆ VMを書いた(C#) * x86ではない!
ttp://up.x0000.net/files/TSimulang.zip
☆ malloc / free を実装してみた (C#)
ttp://up.x0000.net/files/TMallocTest.zip 確かに>>1の概要欄にも答えるとは一文字も書かれて無いw >>508
逃げるもなにも、scanfの話なんて出尽くしてるじゃん。
他になにを話したいの?
役に立たないことブツブツ言ってないで話を振ればいいじゃん。 >>491
そういうのが欲しくて自分で書いてしまったんですけど、すでにあるんですね…そう思う人は結構いるってことですね
>>492
getline() の中の malloc() が失敗したことがわかるんだったら、私は問題にしないですね >>511
QZ先生がどのくらいのリスクを前提に言っているのかにもよりますけど、
上限なき malloc については、リスク回避の点で、私はやっぱり問題にしたいですねえ。
おっしゃる通り、malloc が失敗を返した場合は概ね問題ないと思うのですが。
逆に malloc が成功を返した場合はどうです?
共有リソースとしてのメモリを奪いきってしまった結果としての成功であるなら、
OSによっては、他のプロセスのメモリ確保失敗に伴う致命的エラーを誘発するなどして、
広範囲な問題を引き起こすやもしれません。
先人の知恵として、システムコールやAPIの仕様として、インターフェイスにせよ、内部的にせよ、上限を設けてあると思います。
getline の内部は見てないのですが、極端に大きなサイズになりそうなら、malloc を呼び出す前に、
上限値を超えました的なエラーを返すような、慎重なコーディングになっていることを期待したいところです >>511
実行環境に固有の特殊事情ではあるけど
Linux だとメモリが足りなくても malloc が成功する場合がある。 (オーバーコミット)
malloc の返り値を気にしても無駄。
想定以上の巨大な行の読み込み (メモリ割り当ての失敗) に対して
何か対処する機会なくプロセスごと殺される (OOM Killer) かもしれないので、
想定する上限があるなら設定できて欲しいよ。 ドライバレベルの仕様に詳しい人って、そこそこ不幸だよね😅 >>513
メモリを確保するだけじゃなく中身を詰めて返すから、内部でメモリ量を超える malloc に成功しながら中身を詰めてる過程でメモリ不足で落ちそうだね。
上限設けてないと回避できない深刻な問題になりそう。 >>518
岩の中にテレポートしそうなあたりじゃないかな そういえば、初期のosxはオーバーコミットと動的スワップの合わせ技で、ディスクの空き容量が
少ないとよく固まってたな。しかもfinderではまだ空きがあるように見えても実際には最小空き容量に
引っかかるという油断のならない仕様だった。 >>522
トリッキーなやつで普段お目にかかれないやつです >>524
いいですね
これは何をやってるコードですか? >>524
殺意湧くコードだわ。
信じられないだろうが、こういうの書きたがるやつ沢山居る。 昔観た砂嵐のもこんなんだったな
マクロ使ってたかどうかは覚えてないけど
いずれにしても中身に意味があるとは思えない わざと解りにくく書いたコードだぞ
「ちゃんと動くプログラム」という制約のもとで
解りにくさを競っているんだよ >>525
岩の中にテレポートしそうなあたりじゃないかな >>527 本人じゃないけど
成型ツールで戻せば良いとか言うレベルじゃなくて
マジックナンバー使いまくりの手動最適化コードとか
読み難くする以外のメリットなんにも無い時間の無駄
難読化ツールとかの話も関係無い 人間が読む事を想定してないコード
なんていう発想は無いのか 難読ソースコンテストってのがあるって25年前に聞いた。 どんなネタでも餌にして生きていける人って別の意味で浦山 って言うか >>1 でリンク張られてるサイト
C FAQ 日本語訳
http://www.kouno.jp/home/c_faq/
の 20.36 が 国際難解Cコードコンテスト(IOCCC) の紹介ですよ。
まぁ知らなくても実用では少しも困らないネタ話だけどね。 IT掲示板群 ttp://x0000.net/forum.aspx?id=15
学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
ttp://x0000.net/topic.aspx?id=3631-0
UIライブラリ (C#, 2D) を作ったよ
ttp://x0000.net/topic.aspx?id=3688-0
連続と離散を統一した!
ttp://x0000.net/topic.aspx?id=3709-0
4Dエンジン(画像有り)
ttp://x0000.net/topic.aspx?id=3677-0
matrixのライブラリ
ttp://x0000.net/topic.aspx?id=3711-0
ある強力なFor関数
ttp://x0000.net/topic.aspx?id=3630-0
SQLライブラリ
ttp://x0000.net/topic.aspx?id=3675-0
☆ VMを書いた(C#) * x86ではない!
ttp://up.x0000.net/files/TSimulang.zip
☆ malloc / free を実装してみた (C#)
ttp://up.x0000.net/files/TMallocTest.zip うん、トリプルって読み方する人には会ったことがないな 東京が goto キャンペーンから外されて本当に良かった。 東京以外は goto を使ったCプログラムで溢れかえるんだろうなあ・・・ 奥村先生が書いてらっしゃる
「いまさらC言語」
https://scrapbox.io/imasaraC/
って、「初学者がC言語を学ぶ」という目的にはそぐいますか?
偉そうな言い方なんですけど、C言語の基礎を一通りなぞる感じには見えませんでした。
ですが、もしもC言語の基礎をこの記事で勉強できるなら、
奥村先生直筆の日本語文書ですし、ぜひ参考にさせていただきたいのです。 散文っぽくて体系的じゃない感じは受けた
「いまさら」であって「初めての」ではないので文字通り受け取って
既に知ってる人が改めて見直す機会には良いんじゃね
scanf
https://scrapbox.io/imasaraC/scanf()
fgets
https://scrapbox.io/imasaraC/fgets() >>565
ありがとうございます。
入門書と銘打ってる文書にします。 すっごいポンコツPCでmacでCSV作って作ったの読み込んで計算して表示してって10回ぐらい繰り返したら同じデータ表示されるの? ポンコツだとたまに計算間違うから無理じゃないかなあ >>567
本当にポンコツであれば、主メモリーかHDDが壊れている可能性がある。 >>567
なんかこんな環境でやったらCSVのデータが更新されなくて10回全部同じ計算になってるって事が起きたから
やった人はsleepで遅らせたら変化したって言ってたからそんなことが起きる事があるのかって不思議に思ったわ メモリは思ったより信用できない (ちょいちょい化ける) という話を
何かのウェブブラウザ関連の文章で読んだことがあるような
気がするんだけど思い出せない。 簡単に化けるから誤り検出符号なるものが存在している
HDDはもちろんメモリだって物理的に劣化する ディスクキャッシュでなかったかな。
毎度syncするようなkernelパラメータか何かを与えないと旧データを読み出すような事象が昔あったような。 >>571
DRAMのメモリセルに宇宙線が当たったりね
でサーバー用のメモリにはECCがついてるし
HDDはRAIDで耐障害性設計もする C言語を3ヶ月前から勉強し始めたものです。この間、C言語3級を受験しました。
C言語かなり難しいです。
苦労しながらC言語学んだ方いますか? 苦労せずに学んだやつなんているのか?
元々アセンブラ屋でアドレスやポインタが当たり前だった俺でさえ
それなりに脂汗かきながら憶えたぞ 独学で始めたからリンカの使い方とかよく分からず、C のソースを全部 include してたな。 多分分割コンパイルのやり方を知らなかった頃の話だろう >>583
そそ、そういうこと。
んで複数のソースを include するだけのファイルを作って、それのことを makeファイルと言うんだと思ってた。 このコード最適化の余地ある?-O3でやっても1900msとかかかるんだけど
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int f(int size, int *data1, int *data2) {
int r = 0;
for (int j = 0; j < 100; j++) {
for (int i = 0; i < size; i++) {
r ^= data1[i] & data2[i];
}
}
return r;
} int main(int argc, char *argv[]) {
int size = 1000 * 1000 * 100;
int *data1 = (int*) malloc(size * sizeof(int));
int *data2 = (int*) malloc(size * sizeof(int));
//setup test data
srand((int) time(NULL));
for (int i = 0; i < size; i++) {
data1[i] = rand();
data2[i] = rand();
}
int sec, millisec;
struct timeb timebuffer;
//start
ftime(&timebuffer);
sec = timebuffer.time;
millisec = timebuffer.millitm; // benchmark
int r = f(size, data1, data2);
// end
ftime(&timebuffer);
sec = timebuffer.time - sec;
millisec = timebuffer.millitm - millisec;
millisec += sec * 1000;
printf("%d ms \n %d", millisec, r);
free(data1);
free(data2);
} たしかにrが0になるが
たぶんsrand, randで値の分布が一様じゃないせいか?
Javaとの性能比較してたんだけど乱数生成法が合わせれないな Java(VM)とCという言語の比較をしたいのかこのソースを最適化したいのかrandの仕様を統一したいのか意味不明だわ JavaとCの性能比較で「Javaは高速だCに負けてない」とか
「JITやGCが動作する時に遅くなるだけだ」とか良く言われてる。
でもこういう単純な配列処理でCの方が3倍くらい速いよな、と思って。
この処理は計測中にヒープ割当が無いからGC関係ない(Javaでオブジェクトを作成するとGCのためのオーバーヘッドがあるらしい)。
JavaでJIT効かせてから計測してもCが4倍弱速かった。
最初1900msもかかるといってたのは勘違い。Cの方が4倍弱速いから予想通りの性能だった。
Javaの性能に関する言説を見渡しても、なぜこういう処理でJavaが遅いのか説明が無い。
大量のデータを処理しつつ特定の値に収束しない良いベンチマークコードがあればいいんだが。
足す引きを交互に繰り返すか。 >>586
data1[i] & data2[i] の計算を100回もやることはないから
int f(int size, int *data1, int *data2) {
int *data3 = (int*) malloc(size * sizeof(int));
for (int i = 0; i < size; i++) {
data3[i] = data1[i] & data2[i];
}
int r = 0;
for (int j = 0; j < 100; j++) {
for (int i = 0; i < size; i++) {
r ^= data3[i];
}
}
free(data3);
return r;
}
ってやると多少速くなるかも
あとは分割してスレッドで並行して実行するとかかな これで収束しないし毎回ランダムな結果になる。
long f(int size, int *data1, int *data2) {
long r = 0;
for (int j = 0; j < 100; j++) {
for (int i = 0; i < size; i++) {
r += data1[i] - data2[i];//ここ変えた
}
}
return r;
} なんだ、^ の意味わかってなかったのか。
ていうか、コードの最適化を求めるなら、
そのコードの目的のほうが先に存在するはずじゃないのか?
コロコロ変えてさあ最適化しろとかおかしいだろ。 ^ だよ
最後のやつで + を ^ にしたらどうなる? あr=0でr^=使ってたからか
演算子の意味じゃなくてr=0で始めてる事との整合性に気付いてなかった
r = rand();
r ^= data1[i] ^ data2[i]
これなら収束しないはず 目的の明確でないベンチマーク作っても無駄だよね。
何を調べたいの? > この処理は計測中にヒープ割当が無い
って書いてあるけどガッツリ malloc してるし本当に何がしたいのか良く分からない >>600
なんで代入されないんだ?
>>602
>>593
>こういう単純な配列処理でCの方が3倍くらい速い
>>603
「計測中に」はstartとendの間にという意味。 >>586
大いに改善の余地あり
0になることを仮定せずに真面目に計算するとして
データがメモリがキャッシュに入るとすると
計算の依存関係ありまくりだから
ほぼレイテンシ待ちになる
ループ4周を展開して
rを4個に分けるだけで速くなりそう
SIMD命令が使えるなら
非常に効果がある形なので
使えるなら使う
この場合も演算の依存関係は減らすこと
データがキャッシュに収まらないなら
メモリ速度で決まるからあまり関係ない 代入されないんじゃなくて偶数回^すると元に戻るのか >>605
> なんで代入されないんだ?
代入はされているが、100が偶数だから >>604 の言うように0に戻ってるだけ。 二重ループにして外側が偶数回だからか。
「同じ乱数列を偶数回XOR走らせたら元に戻る」と。
>>600や>>604が言ってるのはそういうことか
勉強になった あーじゃあr=0で始めてたことは関係無くて、
単に二重ループの外側が偶数回だと無意味だと。
r=0で始めてもXORならちゃんとビット列変わってたけどXORの性質から元に戻ってたと。
コンパイラがそれ知ってたら最適化して処理消しちゃうから良くないな。
XORのその性質を知らなかった より正しく述べておこう
・1回でも101回でも同じ結果なのでXOR版では二重ループの外側が無意味
・data1, data2がどんな数列でもXORの性質は同様にある
ID:lGyqioywHとID:YNla03BQMはこれを言ってたんだな より正しく述べておこう
・1回でも101回でも同じ結果なのでXOR版では二重ループの外側が無意味
・data1, data2がどんな数列でもXORの性質は同様にある
ID:lGyqioywHとID:YNla03BQMはこれを言ってたんだな かようにベンチマークっていうのは難しいんだ。
CPUの比較をするだけでもいろんな提案があって
SPECとかはなんとか信頼されているが、
言語間の性能比較とか素人が適当にでっち上げても、
そのプログラムが悪いだけじゃねってなるのがオチ。 最終的に 0 になるだろけど、この計算は愚直に行われるんでしょ。
答えが 0 にしかならないことと C と Java の速度差がそうなることとはまた別の話だよね。
って、コードの最適化の話だったんだっけ? Cがこの処理でJavaより3〜4倍速い事は確認できた。
0に収束する事とそれは無関係。
以下、一応書くけど完全にスレ違い。
このような単純な配列処理でCとJavaの速度差がなぜ生じるか?はまだ分かってない。
・HotSpotは配列の境界チェックを除去できる
・一般論としてJavaが遅くなる原因としてJITやGCが挙げられるがこの単純なプログラムではそれらの影響はない
予想
・1命令で処理できるサイズが違っている?約4倍の速度差はベクトル演算の差で説明できそう。
だとしたらなぜJavaのJITはそれをやらないか?
・CPUキャッシュの問題?Javaの場合CPUキャッシュが別の何かで埋まってしまっている可能性 そもそもjavaがc/c++並に速いとか、かなり嘘や誤魔化し入っているから
速度差3-4倍で済むなら十分健闘している
javaのコードを移植して、無駄にmalloc freeしまくったりする糞コードならもっと迫れるだろうけど >>615
そもそもJITが吐くバイナリを逆アセンブルして比較しなきゃしょうがないんでね?
そのようなことが可能かは知らないけど、処理中にデバッガで無理矢理止めればわかりそうな気はする 最初の>>586の問いがベンチマークを意図してるとは思われてなかったから{return 0;}で良いんじゃね?ってなったんでは javaの配列は特別な宣言無しに別スレッドでこっそり書き換えてもちゃんと反映されるわけだから、単純処理であっても最適化にも限界があるだろうな。
Cの場合は、他で書き換えられるかもと指定しておかなければ他所のことなんておかまいなしに処理できるから、その点だけでも有利だよね。
>>586 のコードのなら、i のループに入る前に data[j] を変数に取り置いて i のループ内で使用するようにすれば、java の方では高速化されるんじゃね。
C ならそれをコンパイラがやってくれてそう。 逆にCの側で配列を volatile にしておけば Java との速度差は小さくなるかもね。 じゃあjava.util.concurrent.atomic以下にある配列クラスは全部廃止だな >>587
巨大サイズメモリで簡単な演算だから
ほとんどがメモリアクセス時間だろ 簡単な処理のために巨大メモリをスキャンするのは超無駄 C版
size
1000*1000 * 1 20ms
1000*1000 * 10 191ms
1000*1000 * 100 1893ms
線形な変化だからCPUキャッシュに載り切るかで性能が分かれるという事が生じてない。
たぶんCPUキャッシュは「繰り返し使うデータ」じゃないと有意義じゃない。
この処理だとCPUキャッシュ上のデータを排除可能になるまでの時間がボトルネックで、
つまり「CPU上のデータを処理しきって次の要素を受け付けれるようになるまでの時間」が支配的なはずで
そこがベクトル演算で高速化してる。
Java版も線形に変化した。
で、Javaのコードでr += data1[i] + data2[i]のところでdata1のみにしたら2倍速になったからベクトル演算未適用が原因でほぼ間違いない。
その行で+か-か^か&かは結論に影響しない。 >>622
ほんとだw
data1 か data2 かは置いといてもどっちも i を添字とするループか。
マトリクス状に組み合わせてるんだと錯覚してたすまん >>623
値が volatile なことと操作が atomic なことは別の話だよ。
自分が書き換えない同じ領域を複数参照するとき、それを他の誰も書き換えないならその参照は一度目の値と同じになる前提で最適化できるけど、他の誰かがいつの間にか書き換えることがあるならそういう最適化はできなくなる。
そういう領域であることを明示するのが volatile。
atomic は同じ領域を誰かが書き換える前提なので基本的にその領域は volatile だけど、それに加えて値を参照して手を加えて書き戻すなどの一連の手続きの途中で他の誰かにいじられないことを保証すること。
それを CPUレベルの命令で行うかソフトウェア的なロックで行うかで色分けされてるだけ。 メモリアクセスの影響がないなら
iとjのループを入れ換える
ループアンロール
rを偶数奇数で分ける
SIMD
などが有効 >>627
同じメモリに100回アクセスしてるんだから
メモリサイズが小さければキャッシュが効くはず >>632
確かにそうだ。
でも1000 * 100も試してみたが2msで線形だった。 >>629
別スレッドからの値の書き換えについて話をしていたよね?
だったらvolatileは何も保証してくれないよ >>629
分かってると思うけど誤解なきよう勝手に補足するけどvolatileの最適化抑制はreadだけではなくてwriteに対してもな。
ドライバ書いてる人には常識レベルだけど。 volatile ってスレッドに限らず値が知らない内に変化する可能性のある何かの入力でも使うよね。
例えばマイクから拾った音を A/D 変換した値がメモリマップドI/Oで特定のアドレスのメモリ読む方法で読める場合。
CPUが予想不能な形で値がコロコロ変わるので volatile にせざるを得ない。(volatile って揮発性とか不安定って意味だし、言葉の意味そのままだ)。
これは読む側だけど書いて何かを出力する場合も、書いた値を読めないような作りになっている場合もある。
1を書いたのに直後に読むと0だったりなんていう事はあり得る。要するに一々覚えていない。または覚えていても読み出しに対応していない。
そんなハードウェアが接続されていたらそうなる。 そりゃ、外部装置と連動しているから、値がいつ変わるか分からない
外部装置が読み書きしたら、合図として、0.1ms 後に、値を反転させたりとか、
色んな事をするから、予測できない volatileは変数(I/Oアドレス)に対するアクセス行為は保障するけど値そのものに対しては何の意味もない
そもそも外部要因で変化する値に対して干渉するのは不可能 どこから干渉するとか出てきたんだ…
知ってる知識を開陳したくてしょうがないんだろうなw volatileな変数を読むのは怖いよね
ワード単位ならいいけど、構造体読むときはチェックサム欲しくなるよね 別に怖くはないだろ。
他所と排他するなりしかるべきタイミングでアクセスすればいいだけなんだから。
排他や同期が必要な領域にそれをせずにアクセスするならただのアホってだけで、volatile がどうとかいう話じゃない。 >>642
それはatomicとかクリティカルセクションの話であって
volatileで何とかしようという発想がそもそも間違いだ 「書きこんだものの読み込んでないからコードから消しちまえ」
「読み込んでるけど、代入以降値がかわる気配がないから、読み込みを止めて固定値にしちまえ」
これを抑制するだけ
書き込や読み込みを記述通り生き残らせる W=>R : R省略
R1=>R2 : R2省略
W1=>W2 : W1省略 volatileの意味を知らない人 vs volatileを覚えたての人 30年くらい前までドヤる人が好んで口にしてたけどね
そういう人はC89ができたらピタリとやめた
今まだ言ってる珍獣って何なん? C89以前のK&R Cは個人的には好きなので
gcc -traditional復活して欲しい 関数定義で引数が()の外に書かれる記述みると、
今は違和感が湧いてしまう 書き方が違うだけなら古いスタイルでもいいんだけど、型チェックが緩いんだよな。 引数の数を間違えているのに黙って通してしまう例。
https://wandbox.org/permlink/FEu474UVSsilTq0L
最適化オプションを付けたらフロー解析も強まるのか警告してくれたけど。 あのなあ、おまえら。。。。
K&R Cに対する批判なんて今さらドヤるか?
規格Cを憶えるときにプロトタイプは何のためか
説明受けてないやつがここにいるとでも思うのか? >>663
やっぱり C99 or later を叩くのがかっこいいですよね 浮動小数の演算で生じる誤差は常に絶対値が小さくなるように行われる、
という前提は正しい? >>668
ライブラリやFPUの実装の話だね
例えばだけどIEEE754の定義では
仮数部は1.xxxxxxと、整数部が常に1なので
整数部を省き、その分の1bitを小数部に回す「ケチ表現」で
誤差がなるべく小さくなるように工夫している >>668
浮動小数点制御ワードの設定によっては丸め方向が変わるから、必ずしもそうだとは言えないかも。環境によるのかもしれないけど、詳しくは知らない。
_controlfp_sとかでググってみて。 doubleを分解(0.1や0.3とかでかけて複数のdouble値にする)して足し合わせて比較、
という処理を無限回繰り返して元の絶対値を超えていたら停止、
みたいなテストコードを書いてみたけど、低確率で元の絶対値を超える。
この誤差が分解と足すときどちらで生じているか分からないが
なんにせよ浮動小数点数演算の誤差で絶対値が増加する場合があるようだ。 あ、誤差の絶対値ではなく、結果の絶対値ということ?
俺の勘違いだったら悪いんだけど、それじゃ意味なくね?
結果が正数ならともかく負数の場合デメリットだけやん 丸めモードによって変わるだろうに
絶対値が小さくなるのはround toward zeroにしたときだな Cのソースコードを解析するツールで有名なものって何かありますでしょうか? デファクトスタンダードなCのコーディング作法を手っ取り早く
身につけるために何をすべきですか? 所属がわからないと何とも言えませんね。
社名と部署お願いします。 車載の組み込み系以外は
それぞれの会社にコーディング規約あるんじゃない?
知らんけど お手本のプログラムを上司に見せてもらい完コピする。 >>681
組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド、MISRA‐C研究会、2006
この研究会は、トヨタなど大企業から、数十人のベテが集まって、
欧州人に聞きながら、作った本
未だに、コーディングルールのバイブルだろ
元々は、Andrew Koenig の本
C Traps and Pitfalls, 1988, c1989
Cプログラミングの落とし穴 >>685
>数十人のベテ
司法試験板をみると「ベテ」というのは30代以降の複数回受験者のことらしいですよ
文脈によっては veteran は階級を問わず退役軍人を意味することもありますし‥‥「わしが現役の頃には」を壊れたレコード盤のように繰り返すイメージとか
ベテランという言葉に必ずしもプラスイメージが伴っているとは限らないことはしっておいたほうがいいんじゃないですか? 能書きはいいから内容を見ろや
あれを見てくだらねえと思うことが何もないやつは
自分がなさすぎだ >>682-684
なるほど,やっぱり利用場面とか会社の文化などで
全然違ってくるんでしょうかね
>>685
ありがとうございます.見てみます. 何も知らないなら手あたり次第写経してみ
それで何でこんな描きかたになってんの?
ってここで質問繰り返せば良い
みんな暇だから答えてくれるはず printf()の戻り値は本当に捨てて良いんですか?
とか >>692
捨てては駄目だな。答えが表示できなくなる。
#include <stdio.h>
int main()
{
printf("%d\n",printf("1+2+3="));
return 0;
} 返却値を捨てて良いか否かを他人に聞いて
そこに固執する教条主義者か
いかにもMISRA大好きそうだな MISRA も、MISRA 対応性的解析ツールを公開してくれていてもよさそうなものですが‥‥ただで MISRA だって MISRA を採用する場合に何がなんでも全ての項目に準拠しなければならないというわけではない。
(逸脱する場合には文書化しておくことを推奨してはいるが。)
ただ、気を付けなければならない箇所がまとめられているというのも間違いないので、
目を通すくらいのことはしたらいいんじゃないの。
俺は読んだことないけど。 俺は規格や仕様に縛られないで自由にプログラミングするのさ
翼が生えた蛙みたいにケロケロいいながら大空を羽ばたくのさ いや規格は守らなきゃ
工業人の法律みたいなもんだから
MISRAの話がどう化けると仕様になるのかは意味不明 >>704
規格が法律に例えられるように、MISRAは憲法になぞらえることができる >>705
なんでMISRAの方が規格より上位なんだよw
せいぜい一地方都市の条例程度のものだろう でもやっぱりどれくらいMISRAに準拠してるかチェックするツールが全く出てないのは不自然
もしかしてMISRAって目視チェックを前提にした規格なのか?
それとも企業で門外不出のツールになってんのか? 【手を挙げて】横断歩道を渡りましょう
↑
この程度だよ
憲法だの条例だのと違い司法機関は相手にしない 小池百合子が掲げるフリップみたいなもんだろ
今年の夏は特別な夏です、破廉恥なコードは自粛しましょう 「警報!侵蝕されてます!パターン青です!コードを切り離せません!」
夏はこれ >>707
全くて、市販の静的解析ツールならいくつかあるじゃん。 おまえらミスラの話と見せかけて髻(みずら)の話につなげようとしてんだろ
どうせここで髪の話して俺の悪口言う魂胆なんだろ
おまえら最悪だな >>712
髻なんて糞、そんな下らないものを気にする奴は馬鹿、という流れでお前さんへのエールのはずだったんだ >>711
MISRA の対応するコメントを付けてくれる性的解析ツールは、無料で提供されるべきでしょう、業界標準を目指すのなら >>715
規格書の類すらみんな有償なのに夢見すぎ。
そもそもMISRAって金も出せないアマチュアに使ってもらうようなものでもないしね。 >>716
でも MISRA の対象者レベル設定ってアマチュアレベルでしょう? 金取るかどうかの話をしているのにレベルの話を持ち出したのは意図的に話をそらしたわけ?
それとも日本語をちゃんと理解できない? >>718
無論、前者ですね、というかモノの値段はその価値と深い相関があるのが普通でありマトモだとも思いますから、
支払う価値の話に対して対象レベルの話を持ち出すことは、あながち間違っているとはいえないでしょう? 言ってることがむちゃくちゃすぎw
やっぱり日本語もダメだろ VSCode の拡張機能で、misra で検索すると、これが見つかる
Parasoft C/C++test Standard
https://marketplace.visualstudio.com/items?itemName=parasoft.vscode-cpptest
https://docs.parasoft.com/display/CPPTEST20201
C/C++ Static Analysis, Safety and Security Coding Standards,
MISRA C 2012, AUTOSAR C++ 14, CERT C/C++, and others. >>717
アマチュアとアマチュア以外の定義を述べよ。 プロってどの位のレベルなのかに興味津々なんだろうな
サンプルがなくてw 複雑になっても自分で何を作っているのか理解しているかしていないかぐらいの差じゃないの? >>722
トータル 1 万ステップ以上のプロジェクトを扱ったことがあればプロ、そうでなければアマ、というのはどうでしょうか?
無論、私は後者です 業として行っている個人やそのような組織に属しているのがプロ それを生業にしてるならヘボかろうがプロではあるな。
んで世の中ヘボが相当数いる。
百人単位のプロジェクトになると7割はヘボ。
入社したてのほとんど何もできない新人君とかも混ぜ混んでくるし、本当にひどい。
でもみんなプロ。 プロアマの基準にステップ数なんざ関係ないが1万程度1人で組める規模じゃん
成果物で金稼いでりゃプロで良いと思うし、プロでもひどいの居ればアマでもすごいのは居る >>732
>成果物で金稼いでりゃプロ
なるほど‥‥感心しました 長時間労働に耐えられる体力があるのかもしれんし、
有力者に取り入る能力が高いのかもしれんし、
幸運値が高くてなんとなくやっていけてるのかもしれん。
それも成果。 ユーザーからしたら、どんなクソコードが走ってようがテストされ尽くして品質保証がされていてちゃんと動いてるならどうでもいいよ。
開発者からしたら、クソコードは工数が膨れ上がる原因になるからやめて欲しいけど。
そして品質保証プロセスがあると面倒臭いルールだらけで足止めを食らうからそういう世界では開発したくない。
でも、MISRAとかはそういう面倒臭いルールで品質を保証するためのもので、辛い開発プロセスを我慢して製品を作り上げられるのはプロの開発者だと思うよ。
それなりに優秀な人、ぐらいだとアーキテクチャを知り尽くしているところまでは行ってないと思うし、
思わぬところで不具合を発生させてしまうものだから。
エレガントなコードかつ、品質の保証範囲も広いコードを書ける開発者なんか極少数なんだからミッションクリティカルなところでは規約で縛ってくしかないと思うよ。 本書いてるやつらの個人的な好みだの
大事にしたところで結局使えねえバカに合わせろだのと
くだらねえことばかり分厚い本1冊渡してすべて読んで従えなんてやると
やる気なくさせるだけだ 著者の好みとか、そういう次元ではない
日本の大企業のトップ、50人が集まっても、誰も規格を知らない。
規格の研究は、それだけで何十年も掛かるから、開発者ができない
基本、企業には、そういう開発しない人は、いらない
だから日本には、規格に精通した研究者がいなくなった。
江添亮ぐらい
だから、欧州のMisra-C に聞きながら、作った。
でも、欧州側にも詳しい香具師がいないのは、同じ。
日本側が、欧州側の間違いを訂正したりもしてる
企業としては、規格だけを何十年も研究しているような香具師を雇わないのだろう。
だから、まぎれなく書かないと、誰も規格を調べられないから、困る 馬鹿か
家電量販店くらい覗いてみろ
新規格が発表されるたびにメーカー各社いち早く対応製品出してるだろ 成果物という言い方に違和感。
普通に製品で良いのでは? コンパイラの新しい規格が決まりました
対応する新製品、本日発売です >>738
前々から馬鹿だとは思ってたが、ここまで馬鹿だとは 社内で使うツールなんかも製品なんていうのか?
むしろ成果物のほうが一般的に使う用語だと思うぞ
もしかしたら業界によって違うかもしれんが
大体の業界でプログラムだけで製品にならんからな >>740
成果物は製品に限らんから
テストコードや、テストデータ、テスト結果のドキュメントとかもあるし つまり間接成果物か。
作る意味あんのそれ
一銭たりとも稼いでないじゃん
それとも中間体なの 稼いでるでしょw
そういうのでお金もらったこと無いの?
お仕事知らなすぎでしょ やっぱり視点がここまで違うんだな
お前にやるカネなんてどうでもいいよ
製品が稼いでくるカネに興味あるんだよ
だから間接成果物だろ
経理の奴らにだって給料渡してんのは誰でも知ってるよ テストもされていない作りっぱなしの製品にお金払ってくれる顧客ばかりじゃないしなぁ >>748
> 副産物って言うかな
言葉遊び以前にそれ全然違う言葉だぞw >>750
まじで知らんのか?
設計とかテストだけ受託というお仕事もあるんだよ
もちろん納入したドキュメントに対してお代はいただくけど、設計書とかテスト結果報告書を製品とか言う奴はいないだろ 会社から外に出るあらゆるものがすべて製品である、ってのなら言いたいことはわかるよ
でも個人的な感覚ではすべてを製品というのは言葉のとる範囲が広すぎる
設計書やテスト関連のドキュメントなんかを製品とは言いづらい
そういうふわっとしたもの含めてプログラマのアウトプットを一言で表すものとして成果物って単語を使ったにすぎない >>747
おまえPGとかいう以前に工業人でさえなさそうに見えるぞ データベースかプロジェクトデータで話が通るように初めからやっとけ。
後でこれがないあれがないあるのが常識やろは馬鹿な日の丸会社に多い。 PGは納品用のコードだけ書いてるわけじゃない
納品に至るまでの内輪で必要になるコードが色々あるかんな
PG経験ないやつに舞台裏の事情がわからんのは当たり前 言葉があやふやな人って本当に仕事してんのか不安になるね でもProductを成果物と訳してるじゃないですか。
これ、オープンソースは無料なので、製品と訳せなかったんですよね?
無料でも製品で良いのでは? 念のため記しておきますが、成果物という言い回しは昔からよく使われていたものではなく、JFから始まったスタイルです。
つまり翻訳に起源があります。 開発費だけの受け取りは不正の温床となるので必ず物の納品を義務化しています。 そういう場合は、JIS用語である中間製品、半製品と言ってるじゃないですか。
オープンソースのときだけ成果物というのは違和感がある。 >>762
我が社では、成果物という言い回しはJF以前からよく使われていたなあ。 大企業間の契約書でも実担当者間の会話でも普通に使われる言葉だし、違和感があるのは単に自分の周りで使われてなかっただけでないかと。 >>754
本当に話が分らんヤツだな
先方に納めたテストは、先方で『稼働』して直接はカネ稼いでないだろ
お前がいくら貰ってようとそんなの関係ない
作ったモン書いたモンが納入先で金稼ぎのツールとして動いてるかどうか、だ
ツール使ってる側から見て、それが直接稼いでるから直接成果物だ
書いてる側の視点なんてのは本当にどうでもいい
お前がどんだけ苦労して作ったとか、作るためにカネ貰ったとか、全くそういうのは関係ないし、不要で、いらないんだ
主観まみれの感情論や精神論は気持ち悪すぎていらないんだよ
で、顧客は、エンジニアが作った器械装置やプログラムを使って稼ぎ出すカネの方に興味がある >>768
ルールが理解出来ない
ルールは理解出来るが守れないまたは守る気がない
こういう人は頭の悪い人だから話が通じると思っちゃ駄目だよ アマチュアのプロジェクトにへっぽこプログラマは参加できないが
プロのプロジェクトはへっぽこプログラマの方が多い >>772
中国の方ですか
やりたいことが金もうけだけなら不動産屋はどうですか 間接成果物を作るのは無駄、というのは、
顧客が絶対チェックしないんだけどなぜか成果物として要求される、
中間工程を納品用にドキュメント化したもの、を作るのが無駄と言ってるのかな
まあ、わからんでもないけどそれがあれば顧客に引き継げる場合もあるし、ケースバイケースのような。 >>773
???
なんで支那の話になるんだ?
もしかしてクラッカーのことをハッカーと呼ぶ手合いか? >>773
>やりたいことが金もうけだけなら不動産屋はどうですか
不動産は儲かるのですか?とても信じられませんね
むしろ株でしょう、それも米国株が儲かるのでは? >>775
あなたの世界ではどうだか知りませんが、世間一般ではハッカーとクラッカーは区別せずに両者とも単にハッカーといいます
ご存じなかったのですか?馬鹿ですね >>777
どこの一般だよ
お前らドカタの世界か? >>777
手合いかと聞いているのを知らないからと思ってしまう
おまえさんの脳味噌こそ深刻なバグ抱えてるぜ
PGの世界でどうだか知らねえのか
マジでトーシロだな
この板では家畜以下の身分てことを自覚しろな 投機的な不動産投資は儲からんかも知れんが
マンションとか土地持ってて他人に貸すのは儲かるで >>778-779
世間一般ではハッカーとクラッカーとは区別しません、両者ともハッカーといいますね
狭い業界ではハッカーとクラッカーを区別して、いいニュアンスを持つものだけをハッカーとしたいようですが、世間はそうは見ておらずハッカーもクラッカーもどちらも危ないものという認識だから両者を区別していないのです
狭い蛸壺で自分勝手にルールを決めても、そんなことはパンピーには通用しないという、いい例でしょう、ことわざにもありますよね「井の中の蛙大海を知らず」もっとも海水に耐える蛙は私もしりませんが
そうそう、どうしてもハッカーとクラッカーを区別したいんだったら「ホワイトハッカー」という言葉はある程度認知されているようですから、それを使いなさい
早く馬鹿が治るといいですね >>781
まさにパンピーには通じてねえな
おまえだよ、おまえ
ボーガスにすらなれない家畜以下のおまえ >>783
敵地攻撃能力は防衛ですか、それとも侵略に入りますか?
そしてその理由は? >>782
>狭い蛸壺で自分勝手にルールを決めても、そんなことはパンピーには通用しない
>狭い蛸壺で自分勝手にルールを決めても、そんなことはパンピーには通用しない
>狭い蛸壺で自分勝手にルールを決めても、そんなことはパンピーには通用しない
>狭い蛸壺で自分勝手にルールを決めても、そんなことはパンピーには通用しない
>狭い蛸壺で自分勝手にルールを決めても、そんなことはパンピーには通用しない >>785
パンピー認めたか、よしよし
家畜以下なクズwww ここはどこの板で、
なんのスレだかも
見ようともしないのか C言語で制約論理プログラムができるiZ-Cでサンプルログラムを書き始めました。
ちょっと夢があるので見てね。
https://sunasunax.hatenablog.com >>792
本人のふりをして荒らさせようとするのはやめろ 2次元配列への走査方向を行と列で入れ替えた際のパフォーマンスの違いは
何に起因するのでしょうか?
いずれにしてもソース上はランダムアクセスに違いないと思うのですが.
https://ideone.com/VjhO3l >>784
ウィルス持ちの観光客が最強と判明しました 今のPCってメモリーいっぱい積んでいるから、
よっぽど大きな配列出ないと差が出ないかも知れない メモリが連続してる方向に走査すればCPUキャッシュが効きやすい プロセッサのキャッシュにはキャッシュラインと言ってフェッチする単位があるんだよ。
あるアドレスをアクセスしたときラインサイズでフェッチしてあるからその後にそのライン内のアドレスならば速くアクセスできる。
要するに先読みしておいてくれるわけ。 なるほどarr[i][j]へのアクセスでarr[i]の周辺もキャッシュに乗ることになって、
その近くなら早くアクセスできるんですね。
ありがとうございます。 >>801
ランダムにアクセスしたいときは
無意味に配列をコピーしてキャッシュに載せるんやで >>802
無意味なコピーだとコンパイラに見抜かれたら意味ないよね キャッシュに乗せるかどうかってコンパイラの仕事なの? メモリアクセスしないといけないのに最適化でそのアクセスが省略されちゃうってこと -O3でコードが省略されるんですが計測したいのに省略されちゃうと計測できないんですが
-O3は計測するなってことですか? >>809
この前関数の呼び出しコストを計測しようとしたんですよ
void f() { }
みたいな関数なんですけど
でも-O3にすると関数呼び出しが省略されるんですね
このケースってなにかうまい方法ありますか? 処理0個
処理1個
処理2個
の関数作って時間はかって処理1個にかかる時間を引き算 最悪アセンブラ見てステップ数数える
関数呼び出しだけならそんな無いでしょ 中でグローバル変数に代入してみたら?
コンパイラから見て、どこで使うかは分からないと思うよ 動的リンクされるようライブラリにすればいいんじゃね? void f() {}
-O1以上は削除されるみたいですね(Compiler Explorerで確認)
https://godbolt.org/z/rcdh9x -O3でコンパイルした時のものを計測したいんだから
なくなる=時間0が正しいんじゃないの? 前処理マクロの質問です。
ファイルの名前と関数名がコロンで繋がれた文字列を出力するマクロを作りたいです。
具体的には
somefile.cというファイルの中で
int somefnc(void) {
puts(FILE_FUNC);
return 0;
}
みたいなコードが,前処理を経て
int somefnc(void) {
puts("somefile:somefnc");
return 0;
}
というコードに変換されるようなマクロが書きたいです。
どうかよろしくおねがいします。 >>823
ありがとうございます。
__FILE__や__func__でファイル名・関数名が取得できることは
知っているのですが,その二つをコロンで繋いで文字列にする方法が
分からないんです。
言葉が足りなくてすいません。
例えば
#define FILE_FUNC __FILE__ ":" __func__
というような定義では,当然ではありますが,
うまくいきません。
__FILE__と__func__を展開しつつ,
間にコロンを入れて,外側を引用符で囲む,
という操作を実現できればいいのですが……。 >>824
前処理の段階で引用符付いたものに置換するから無理
2つの文字列をくっつけて1つの文字列を返す関数を作り、その関数を呼ぶマクロにするとかすればいける char s[4] = "ABC";
は問題無いと思いますが
char s[4] = "ABCD";
とすると警告出ないのですが
最後の'\0'は無視されるのですか?
それとも意図しない領域に描き込まれているのですか? >>824
fprintf(stderr, "%s:%s", _FILE_, _func_) >>826
仕様書6.7.9に余裕があったらnull文字も書き込むよって書いてあるので、余裕がないからnullは書き込まれてないんじゃないかな。 >>828
ありがとうございます
別の質問なのですが
char s[4] = "ABC";
のとき
printf("%2s\n", s);
で
ABC
まで表示されてしまいます
これを2文字で切るのは
%2s
じゃ駄目なんでしょうか? 出来たかも知れないありがとう
ちなみに
char s[4] = "A";
printf("|%.2s|\n", s); // |A| 右詰めにならない(左に空白一文字分が出来ない)
printf("|%.-2s|\n", s); // |%.0-2s| って表示される
printf("|%-.2s|\n", s); // |A| 左詰めにならない(右に空白一文字分が出来ない)
なんですけど
printf("|%-2.2s|\n", s);
printf("|%2.2s|\n", s);
で自己解決です >824
そもそも__FILE__や__DATE__はリテラルだが__func__ はリテラルじゃないのでそういうことはできない。 >>832
そうなんですね。
とすると,
#define FILE_FUNC(func) __FILE__ ":" func
みたいにして,
実際使う場面で
FILE_FUNC(__func__)
というように引数として渡す,という方法をとればいい
ってことでしょうか。 >>833
あ,当然
#define FILE_FUNC(func) __FILE__ ":" func
のままではいずれにせよ
"somefile:somefunc"
には展開されませんが……。 >>833
#defineで定義してしまうと、再定義でもしない限り、そのソースファイル全体で
一意になる静的なリテラルになってしまうでしょ
一方の __func__ は、各関数内部で、static const char に展開されています
だから、マクロを工夫して置き換えたりするよりも、
>>827 の方法が一番簡潔な方法だと思います >>835
わかりました。ありがとうございます。
>>827さまもありがとうございました。 ところで、何で__FILE__は直に文字列リテラルに置換され
__file__は暗黙に宣言される配列の識別子なんだろうな
まさに822が陥ったような混乱の元だと思うが
そうしなければならない理由があるのか >>837
__func__ のことなら、構文解析が要るからでしょ。
ファイルはプリプロセッサの中で自然にわかるだろうけど、現在位置がどの関数の中か(あるいは関数の外か)はわからない。 >>838
ああ、そうか
翻訳フェーズ(7)でやっと関数名が判明するから
翻訳フェーズ(4)では置換できないってことか
当たり前っちゃ当たり前だな
気が付かなかった >>401
> 何に使うかでそんなに変わるか?
亀レスでごめんなさい。
GUIを含むかどうかでちょと変わると思う。
WindowsならやはりVisualStuidoが便利だった。
Linux、UNIXならgcc,vi,makeの3種の神器かな? for文の制御式にポインタが単独で使われているコードの意味が分かりません。
https://git.musl-libc.org/cgit/musl/tree/src/locale/catopen.c#n43
ここにある
const char *path, *p, *z;
path = getenv("NLSPATH");
for (p=path; *p; p=z) { // ← これ
...
}
こんな処理です。
繰り返しの際に実行する式にポインタを置くことで
どういう処理が行なわれているのか解説していただけないでしょうか。
どうかよろしくおねがいします。 *p なら文字終端 '\0' チェックしてるだけじゃね
for (p=path; *p != '\0'; p=z) {
と一緒 >>843
なるほど!
for文の中でpを:ごとに削っていっているので,
それが空になるまで廻すという意味になるんですね。
*p != '\0'はメッチャ分かり易い書き換えでした!
(*pとだけ書いてあっても難なく読めるようにならないと
いけないとは自覚していますが……)
>>844
すいません,ほぼ追加で質問する形になってしまうのですが,
どういうところが気になりますか?
教えていただけると勉強になります。 >>842
*p は、その位置の文字が '¥0' じゃなければループ内に入る判定。
ようするに文字列の終端にたどり着くまでループするということ。
p=z の z は、ループ内で p から見た文字列の中の ':' がある位置の次が入るようになってる。
ようするに path を ':' 区切りにした断片を一つずつ処理してる。 >>844
z = __strchrnul(p, ':'); で ':' 毎に切り出して処理して、次の項目に移動してるんでしょ >>848
たしかになぜstrtok()ではなくて独自関数を使うか気になりますね。
__strchrnul()はここで定義されていますが,
http://git.musl-libc.org/cgit/musl/tree/src/string/strchrnul.c
strtok()の仕様
https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok.html
を見ても,ほとんどインターフェースも同じに思えます。
(引数の型がちょっと違う?)
strtok()関数自体を実装しているならともかく
外部から使用するのにわざわざstrtok()と仕様がそっくりな
独自の関数を用いる理由が分からないですね。 >>850
> たしかになぜstrtok()ではなくて独自関数を使うか気になりますね。
strtok( ) は与えられた文字列書き換えちゃうし内部状態を持つので今どき使うのはやめた方がいいと思うぞ 既存関数を使えばわざわざ文字列をループで処理する必要は無いと思えるけど
例えば昔から良くあるコマンドライン引数をチェックする場合などは
ループで処理するのが一般的かなと思われる
簡単なコードを書いてみたので確認してみるといいかも
https://paiza.io/projects/e/0d-LM04O2-C1g6xC2uXP5w コマンドライン引数にstrtokは全く向かない
引用符使われただけでアウト
ASCIIコードしか想定していない >>851
ありがとうございます。
なるほど,
https://www.jpcert.or.jp/sc-rules/c-str06-c.html
にも strtok() を不用意に扱わないようにという記述がありました。
だからわざわざ,strtok()に似ているが与件文字列を変更しない
っていう内部関数を利用していたんですね。
「区切り文字による分割」みたいな処理をする場合は,
strtok()の挙動を完全に理解した上で使うか,
自分で挙動を把握できる内部関数を作るかにするよう心掛けます。
(自分で1からC言語を書けるようになるのは
当分先のことになるとは思いますが) ライブラリ関数内部で同じライブラリで公開してる別の関数を呼び出すのはエラー時に滅茶苦茶になりそうだから良くない へぇ __strchrnul だと非マッチ時 zがヌルポにならないようになってんのか 文字列はS-JISのこと考えて自分で作るか
逆にunicodeで全部ライブラリに任せるかしてるわ。 こないだユニコード文字列を扱うライブラリを作ったんだが、Poweshellから使うとうまく動作しないでやんの
Bashだとうまくいくからシェルの文字コードが原因かなぁって Poweshell 相手 なら UTF16で試してみて 一時期ソースファイルで使われる文字コードと
テキストコマンドで指定される文字コードで混乱してた。 すみません
visualstudio2019で
scanfてうまく動かないて
書き込みありまさしたが
こちらは初心者です >>866
ماذا علي أن أفعل لتحسين عمل Scanf؟ 自分が初心者だった頃を忘れて弱い者いじめするクズばっかり ここの連中は初心者の時でもこんな愚かな質問しなかっただろうからな クズでもなんでもいいから正しい日本語を使って質問しなさい https://hnw.はてなブログ.com/entry/20130406
この記事(海外の質問箱の邦訳)に対するコメントで,
do{
...
} while (feof(input))
というコードが提案されているのですが,どう思われますか。
少なくとも一つの問題点(余分なループ)は克服できている気がしますが。 >>883
コメントって、どこにあるの?
まあしかしそう書いたとしても c = fgetc(input) をやった直後の c の値が EOF かどうかを調べる必要があって、
EOF だったらループを抜ける必要がある。do { ... } while (feof(input)); のループ内に if ((c = fgetc(input)) == EOF) break; を
入れるとすると最後の while の条件は無駄だ。決して EOF に到達していないから。 >>883
中身が空っぽなinputだったらどうする? ま、しかし、よくよく考えてみると feof() って使い所がほとんどないのではないか?
fgetc() が文字だけでなく EOF まで返す仕様になっているから使わずにも書けてしまうよね。
単にEOFになった後かどうかだけを調べたい場合は fgetc() 使ったら無駄な処理になるけど。 fgetc()等はファイルを最後まで読み取った場合だけでなくエラーの場合もEOFを返すことになってるから
どちらの状況か区別するためにfeof(),ferror()はあるんだろ
区別しなくていいなら使わんわな >>883
ダメダメって書いてあるやろ
rero
ferror の条件が成立した場合,feof の条件は成立せず,無限ループになる.
ループ脱出条件にはfread / fscanf / fgetc などの戻り値を使う.
feof は ferror との切り分けにのみ使う.
2014/02/04 関数定義の書式『例えばprintf関数なら、 int printf(const char * format, ...) 』とかで、関数の引数の型指定が含まれてるけど、これの指す具体的な意味って何?
例えば、const char*型が指定されていたとして、
1、「const char*型でなければならない」
2、「他の型も使えるがconst char*型を推奨する」
3、「色々と対応してるけど代表としてconst char*型を挙げる」
4、「1〜3のうちどれか、関数毎にケースバイケースで具体的には決まってない」
関数定義の書式における型指定には、どのような意味が込められてるんですか?
printf関数では、普通に文字列を入れた配列のポインタ(char *型)にも対応してるので、2か3なんだろうけども。
関数定義書式に含まれる型指定は、1〜4のどれなのか、C言語では統一的に指針が決まってますか? printf関数の場合では、「char*型が使えるように見えるけど、色々と問題起きるからconst char*型以外は禁止」ということなんですか。
分かりました。 const char*はchar*の指す先を書き換えないだけで同じものなのでconst char*をchar*で初期化してなんの問題もない。暗黙変換してくれる。
逆は書き換えられないconst char*が書き換えできる様になってしまうので暗黙にはしない様になっている。 こんなこともできるけどね
static /* const */ char str[] = "hello stupid people";
printf(str); 質問のレベルから忖度すると
質問者が気にしてるのは
ひょっとすると
...
の部分の方なのかも知れない #include <stdio.h>
int main(int ac, char **av)
{
int p = 0x000a0d41;
printf((char *)&p);
return 0;
} 関数定義の引数が配列で書けるようになったのはいつから
int func(array[5]){
.......
} 型指定子がないけど暗黙intってことか? 無理だと思うけど >>899
明示変換してるのに暗黙変換もさせるのは読みづらいよ つーかさ
pにアドレス演算子つけてるの
何かがわかってない兆候じゃね? 皆さんのレスを行間を読んでまとめること、こんな感じの理解でいいですか?
代入の際、右辺の値は、左辺の型に暗黙変換される。
int a = 3.5; // duble型リテラルを暗黙変換してaには3が入る
int a = 'a' // const char型?リテラルを暗黙変換してaには文字コードを表す97が入る
int a ="ほげ"; // const char型リテラルを暗黙変換してaにはよくわからん不正値が入る
同様に、関数へ引数を渡すことも代入の一種であり、実引数が代入する側であるから代入式の右辺に相当し、仮引数が代入される側であるから左辺に相当する。
その際、実引数char*型は仮引数const char*型へ暗黙変換される。
int main(void) {
char hoge[] = "ほげ";
printf(hoge); // 実引数hogeは先頭要素を指すポインタchar*型で、暗黙変換を伴って仮引数のconst char*型となる
}
この逆、仮引数char*型に実引数const char*型を渡すのはNG。char*型とわざわざ指定されてる理由は、値を書き換え可能なポインタを求めるためであり、const char*型はダメ。 >>900
型が書かれていないけどそれはタイプミスだとすれば、
配列形式で仮引数を書くこと自体は昔から出来る。
ただし、配列形式で書かれるとそれはポインタに調整される。
たとえば仮引数が int array[5] だったら int* array と全く同じとみなされる。
配列の大きさの情報は無視される。
(ひょっとすると警告を出すためのヒントにするくらいの処理系はあったりするのかもしれんけど。) >>905
暗黙の変換がされる場合とされない場合はあって、
int a ="ほげ";
で暗黙の変換をする保証はない。
C99 だと単純代入で許される型の組み合わせは 6.3.16 に書かれている。
処理系の拡張としてやっちゃうこともあるかもしれんけど、
その場合でも警告は出るんじゃないかなぁ。
> 関数へ引数を渡すことも代入の一種であり
その通りだが、関数原型 (プロトタイプ) がない場合や
可変長引数 (仮引数が ... で表されるやつ) の場合はちょっとルールが特殊な部分もある。
まちがっててもコンパイラが検出できないこともあるので気を付けないといけない。 処理系の拡張ねえ
gccは-pedanticつけないと黙って通す場合あるかんな
>>905
void func(char *);
func("const char array");
これconst違反なのにできちまう >>900
すまぬ訂正
関数定義の引数が配列で書けるようになったのはいつから
int func(int array[][5]){
.......
} >>908
C の文字列リテラルは char の配列ということになっているので char* で受け取れる。
型の視点で見ればそのコードに const は登場しない。
文字列リテラルを書き換えようとした結果は未定義であるにもかかわらず
型に const が付かない C のクソなところのひとつ。
(C++ では文字列リテラルの型には const が付く。) よく見てみたら使ってるツールがC++用だった。
C言語入門本でインストールを促すソフトが大抵Visual StudioのC++で、
意識せずにC++の開発環境でC言語の勉強をしてたんだな。
それで、C言語の挙動だと思ってたのが、実はC++の挙動だったんだな。const の件もそう。 >>909
全然配列じゃないじゃん
int func(int(*array)[5]);
これと同じだよ、配列へのポインタ いくら引数リストに要素数を記述してもコンパイラは無視する
int func(int **array)と同じ扱いでただのニ重ポインタ char **aho = 0;
printf("%p ", aho);
aho++;
printf("%p ", aho);
printf("%p ", array);
array++;
printf("%p ", array); でもまあプログラムの再利用性を考えたら、constの件は、C++仕様に配慮して省かないことが大事か。
C++に配慮したコードを書くことで、C言語でもC++でも通用するプログラムとなり、プログラムの再利用性が上がる。
C言語ではconstを省くことが文法的には認められてても・・・・・C++に流用できないプログラムは、たぶんコードとしては減点となる。 >>914
いや、マジで関数に配列を渡せると思ってるの?
配列の引数はポインタの引数の糖衣構文だよ
どうしても配列を渡したい場合は配列を構造体で包めば要素数を関数に渡すことは出来る >>913
いや、それは >>912 が正しい。
二重ポインタにまで調整されてしまうと
関数 func の中で array[1][3] みたいなアクセスが不可能になってしまう。
ポインタへの調整はあくまで一段階のみ。 >>917
配列を渡すのではなく「配列へのポインタ」だ。
配列は多くの場合に配列の先頭要素を指すポインタに暗黙に型変換されるけども、
それとは別に配列を指すポインタというものが存在し、
指す先の配列の大きさは型情報として保存される。 関数の引数として配列を渡す場合、アドレスと要素数は別に渡す必要がある
関数内で要素数を知る手段はない
int func(int **array, int i, int j) int array[][5] という配列があったとしたら、その先頭要素の型は int [5] なので、
通常通り配列の先頭要素そ指す型に型変換したら int (*)[5] になるんだ。
仮引数の側もそれと同じような調整が入る。 それは配列の変数宣言の場合だ
仮引数の場合には当たらない >>922
JISX3010:2003 から
> 6.7.5.3
> 仮引数を "〜型の配列" とする宣言は、 "〜型への修飾されたポインタ" に型調整する >>924
構文糖だよ。
でも >>913 の構文糖ではないって話をしてる。 >>916
正直言って、const のありがたみが今一つよくわからないんですよね… 確認してみた
配列が仮引数の関数内で配列の型情報は失われて単なるポインタになってる
メイン関数内配列サイズ 20Byte (int[5] = 4Byte * 5)
関数内配列サイズ 8Byte (int* = 64bit)
https://i.imgur.com/nItgOZC.png そう、仮引数の配列要素数はコンパイラに無視される
ただのポインタだから配列サイズは失われている >>926
うっかり変更しようとしたら、コンパイル時にエラーになるでしょ >>927
909読め。一次元じゃなくていわゆる2次元配列な
sizeofに*付けるの忘れないように 修飾なしで const になって、変更可能な変数の場合に指定を付けるようになってればよかったのに
という声は一部では根強く有る。
もちろんそんな非互換な変更を C/C++ が受け入れるはずがないので
あくまでももしもの話というか愚痴の類なんだけど。
でも Rust がまさにそうなったので型の厳しさを指向するなら
デフォルトで変更不能な方が自然なのかもしれんね。
個人的には、 C で意識して const を付けるのは関数の仮引数くらいで十分だろう
という程度かな。 そのかわり仮引数の型付けはかなりしっかりしたい。 リソースが極限まで制限されるような環境下で動かすことがる
ハードに近い部分を書くことが多かった
最適化の精度が悪かった
みたいな時代背景があるのでデフォルトがconstはナンセンス
もちろん今の時代に1から設計するならそういう言語が出てくるのは当然 >>932
>>913は間違いでvoid func(int array[][5]) と void func(int **array) では意味が違うって話だから
それぞれfuncで sizeof(*array) を見ないと意味ない 普通に array[1][3] みたいにして要素にアクセスするときでも
規格上の理屈では *(*(array+1)+3) の構文糖であるということになってて、
じゃあこれを成り立たせるにはどういう型情報があればいいのか
みたいな方向でパズル的に考えて遊んだりするのも面白いかもね。
あとここまでのやりとりで出てきてないっぽいから注意点を示しておくけど、
配列が暗黙の型変換でそれの先頭を指すポインタになるルールの例外が
sizeof を適用したときと単項 & を適用したときだよ。 sizeofと&が例外って言い方よく見かけるけど
気持ちの中ではこっちが本来だね
extern int array[]; と
extern int *array; じゃ
意味違うし >>933
> リソースが極限まで制限されるような環境下で動かすことがる
> ハードに近い部分を書くことが多かった
> 最適化の精度が悪かった
なんの理由にもなってないと思うが…
単にK&Rがそう言うのに無頓着だっただけだろ 何の理由にもなってないのはそのとおりだが
なんで無頓着って話になるんだ?
アセンブラで書いていたUnicsを高級言語で書けるようにしようって作ったんだぜ? >>937
確かに。
暗黙の型変換の方を中心に説明したから例外という言葉を使ったが、
配列がポインタになる方がよっぽど特殊な話だよな。 初心者がややこしい規則をこれから憶えようってときには
確かにあの言い方は情報量少なくて憶えやすそうだけど
初心者を卒業したらいつまでもしがみついてると格好悪いね >>939
例えばintとポインタの扱いとかみたら結構無頓着だと思わない?
別にそれが悪いと言ってるわけじゃない
高級アセンブラとしてはまあ理解出来なくないし当時のマシン環境の制約もあっただろうしね ラクッペペ MM8f-kMIc
↑
こいつは無視でOK そんな感じの2次元配列の引数としてはかけるけど
実際その関数になに代入してもエラー吐くやつとかあったな >>942
> 例えばintとポインタの扱いとかみたら結構無頓着だと思わない?
intをポインタにキャストするようなこと? こういうこと?
void func(int (*array)[5], int **pointer)
{
char a[2][5], *p;
array = a; //ok
pointer = a; //error
array = &p; //error
pointer = &p; //ok
} >>949
そうだけど、それは「危険性」には繋らんよな?
引数関連の危険性というのは大抵、
引数を変に実行してしまうことから始まる訳だから。 >>951
一応は >>949 も未定義だよ。
呼出規約が cdecl だったら余計な引数は捨てられるだけで問題にならないとは思うけど。
余計な引数を渡すのとは逆に必要な引数を渡さないという例も書けるから、
より危険性がわかりやすいかな。
https://wandbox.org/permlink/1F876xK6UZ4wFjAA
余談だけど関数定義は宣言も兼ねるというルールにおいて、
K&R スタイルの関数定義はプロトタイプを持たない宣言でもあるという扱いだから
別途プロトタイプ宣言をする分にはエラーとして検出される。
https://wandbox.org/permlink/4n574f4R9yq0BzUj >>952
> 余計な引数を渡すのとは逆に必要な引数を渡さないという例も書けるから、
たしかにその通りだな。
>>949 のコード例に気をとられて
もとの議論の内容を忘れてたw
thx >>955
普通はする。 すべきだ。 というのがどれほどあてになるか。
普通はすることを (うっかり) しなかったら (エラーとして検出されずに) 通ってしまうってのは
K&R スタイルの関数定義はイケてないねって話。 K&R スタイルでなくともファイルを分割すると宣言と定義の矛盾が検出されなかったりもする。
// foo.c
void foo(int x) {
}
// foo.h
void foo(void);
// main.c
#include "foo.h"
int main(void) {
foo();
}
このとき foo.c をコンパイルするだけなら foo.h は不要だが
foo.c で foo.h をインクルードしておかないと間違いは検出できない。 >>958
大抵の処理系ではリンクエラーにならないよ
C言語だとコンパイル後は引数の情報は無くなっちゃうから 実行時にスタック壊れたり
hangupしたりするんです? >>958
C のオブジェクトファイルは名前しか保存しておらず、
型はヘッダファイルでやりとりするというのが伝統的なデザイン。
だからそれを一致させるのはプログラマの責任。
現代の実装技術なら検出できないことはないはずなんだが、
検出しないのは色々な都合があるんだろう。
>>960
cdecl や fastcall なら関数を呼び出すだけならスタックの整合性が壊れることはないと思うんだけど、
実引数と仮引数がまともに対応付けられていないわけだから
仮引数の読み書き (特に書き込んだとき) には壊れる可能性が高いんじゃないかな。 > 現代の実装技術なら検出できないことはないはずなんだが、
ちゃんとやってるよ
外部参照名の長さの上限を増やすという
後方互換性を損なわない賢いやり方で
それの恩恵を有り難く頂戴しているのがC++ 意味わからん
マンダリングしてるC処理系なんてあったっけ?
別にオブジェクトコードに含ませなくてもデバッグ情報に含ませといてチェックするとかでも良いと思うけどね >>963
32bitWindows向けのstdcallは引数等で使うスタックサイズを名前の後ろに付け加える 本人が間違ってる分には無視すれば良いだけだが
初心者スレで嘘を撒き散らすのは良くないな volatileオブジェクトへのアクセスは副作用を生じるというのを見たことがあるのですが
この場合の副作用とは具体的にはどういう事象のことを言っているのでしょうか? >>968
レジスタなどにアクセスする際に最適化で誤動作しないようにvolatileを付けるのかなと思ったのですが、
逆にvolatileを付けることによる不都合(副作用)って何かあるのでしょうか
それとも最適化されないことを副作用と読んでいるのでしょうか
>>969
最適化しないことによる処理時間増加でしょうか 最適化によって、本来は必要な処理がコンパイラによって省かれてしまうとか コンパイラの判断によって、一部のコードが生成されないとか >>970
プログラミングの世界の副作用とは、不都合とかそんな意味ではなくて、内部状態が変更されるとか、外に何らかの影響を与えるとかそんな意味だよ。
例えばisalpha関数は文字の判定をするだけだけど、printfはコンソールに文字を出力する。
前者は副作用なし、後者は副作用ありだね。
volatileの件はそれが書かれた前後のコンテキストが分からないから何を指してるのか何とも分からんけど、たぶん、>>968に書かれてるように、外部デバイスへの作用のことを指してるんじゃないかな >>970
副作用 (プログラム)
https://ja.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)
> プログラミングにおける副作用(ふくさよう)とは、ある機能がコンピュータの(論理的な)状態を変化させ、それ以降で得られる結果に影響を与えることをいう。
C言語における定義はこんな感じ。
http://kikakurui.com/x3/X3010-2003-01.html#13
> ボラタイルオブジェクトへのアクセス,オブジェクトの変更,ファイルの変更,又はこれらのいずれか
> の操作を行う関数の呼出しは,すべて副作用(side effect)と呼び(11),実行環境の状態に変化を生じる。 回答ありがとうございました
組み込みの資料か何かでvolatileの副作用についての記述があり質問させていただきました
副作用の意味がいまいち分かってないみたいなので勉強します int main(double a, double b)
{
printf("main");
} (void)と(int, char**)以外は処理系定義
コンパイラが対応していれば適格
対応していなければ未定義 crtstartupのお仕事だからコンパイラほぼ関係ないな
大抵の実用リンカは差し替えできるでしょ 数値リテラル「0」の型は何ですか?
int* p = 0; // これはOK
int* p = (int)0; // 明示的にint型にしてから渡すと「int型はint*型に変換できません」とエラー。ということは、この 0 はint型以外?
int* p = (unsigned int)0; // これもエラーで無理。
printf("%zu", sizeof(0)); // 0の型のサイズを調べると4byteと表示される。
この数値リテラルの「0」の型は何ですか?
ちなみに、まだC言語環境を構築してないから、代わりVisualC++を使ってるけど、他の環境でも起きますか? さらに調べると・・・・
キャスト演算子で型を指定した0は、代入の際にint*型へ変換してくれない。
接尾語を付けて型を指定した0は、代入の際にint*型に変換してくれる。
int* p = (long int)0; // NG
int* p = 0L; // OK
int* p = (unsigned int)0; // NG
int* p = 0u; // OK
キャスト演算子で型を指定すると、代入の際の暗黙的な変換が禁止される仕様とかあるんですか? >>980
intだよ
D:\learn>gcc --version
gcc (Rev2, Built by MSYS2 project) 10.1.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
D:\learn>gcc 980.c
D:\learn>gcc 980.c -pedantic -Wall
980.c: In function 'main':
980.c:9:10: warning: unused variable 'p3' [-Wunused-variable]
9 | int* p3 = (unsigned int)0; //
| ^~
980.c:8:10: warning: unused variable 'p2' [-Wunused-variable]
8 | int* p2 = (int)0; // ntintnt*nt
| ^~
980.c:7:10: warning: unused variable 'p1' [-Wunused-variable]
7 | int* p1 = 0; // K
| ^~
-Wallにするとunusedって警告でるけど型の話じゃないね >>981
D:\learn>cl 980.c /W4
Microsoft(R) C/C++ Optimizing Compiler Version 19.27.29111 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
980.c
980.c(8): warning C4047: '初期化中': 間接参照のレベルが 'int *' と 'int' で異なっています。
980.c(9): warning C4189: 'p3': ローカル変数が初期化されましたが、参照されていません
980.c(7): warning C4189: 'p1': ローカル変数が初期化されましたが、参照されていません
980.c(8): warning C4189: 'p2': ローカル変数が初期化されましたが、参照されていません
Microsoft (R) Incremental Linker Version 14.27.29111.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:980.exe
980.obj
参照されていませんという警告は型の話ではないのでここではスルー
型についての警告が出ている8行目とやらはこれ
> int* p2 = (int)0; // 明示的にint型にしてから渡すと「int型はint*型に変換できません」とエラー。ということは、この 0 はint型以外?
隣の9行目は警告されていない(しかも/W4で)
> int* p3 = (unsigned int)0; // これもエラーで無理。
おそらくclが警告しているのはXXX*とXXXでポインタの間接段数を間違えたんだろうということ
これなら9行目はXXX*とYYYで間接段数の問題ではないので黙っているという説明がつく 0だけは特別にポインタにキャスト可能な仕様なんじゃよ
0がいい 0になろう >>980
0 の型は int だけど、空ポインタ定数 "null pointer constant" なので、すべてのポインタ型への暗黙変換が効く。
http://kikakurui.com/x3/X3010-2003-01.html#39
> 値0をもつ整数定数式又はその定数式を型void *にキャストした式を,空ポインタ定数(null pointer constant)と呼ぶ。
(int)0 になると空ポインタ定数ではなくなるので、ポインタに暗黙変換できなくなり、初期化・代入できなくなる。 >>981
int* p = (long int)0; // NG
int* p = (unsigned int)0; // NG
long, unsigned は、int 型と、数値の範囲が異なる。
int 型しかキャストできないのでは? 0も厳格にはマジックナンバーだが
現実のシステムで0番地なんか普通の変数に使えなくていいから
理に適ってる >>982
むつかしくてわからないのでひらがなでおねがいします
>>985
こんな感じで理解しておけばいいですか?
・整数定数式としての「0」とは、ソースコードに直接書かれた「0」で、評価されて返ってきた「(int)0 ⇒ 0」や「4 - 4 ⇒ 0」などの「0」は整数定数式とは言わない。
・同じ0でも、void*型の「0」や、整数定数式としての「0」だけを空ポインタ定数と呼び、空ポインタ定数は代入の際にポインタ型へ暗黙変換できる。
よって
int* p = (int)0; // 「(int)0」が評価されて返ってきた「0」は整数定数式ではないので空ポインタ定数ではない。だから暗黙変換できずに代入無理。
int* p = 4-4; // 同様に、評価されて返ってきた「0」は整数定数式ではないので空ポインタ定数ではない。だから暗黙変換できずに代入無理。
int* p = 0; // 定数式としての「0」だから代入OK
型と値が一緒の、同じint型の「0」であっても、定数式と返り値とでは、それぞれの持ってる機能が違うということですか? >>990
じーしーしーのばーじょんをかくにんしてから
おまえさんのこーどをくわせてみてるんだよ
せんげんだけしてつかってないへんすうがあるのをけいこくされているけど
それはおまえさんがきにしてるかたのもんだいじゃなさそうだねっていってるの >>991
ひらがなでわかりやすくせつめいしてくださったので
あたまのわるいわたしでもようやくわかりました
ありがとうございます NULL == 0 // true
ちなみに0は8進数な NULL == 0 // true
ちなみに0は8進数なんてことなく10進数なんてことなく16進数なんてこともない いや8進数だよ
0xで始まったら16進数
0で始まったら8進数
こんな関数作って見たらわかるよ
syukudai("210") == 210
syukudai("110") == 110
syukudai("010") == 8
syukudai("0x10") == 16 >>996
> 0で始まったら8進数
なら、敢えて数字リテラルで8進数のゼロを表すなら 00 だろう。
つか8未満の数「値」に8進数ってなんだYO!! このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 140日 15時間 37分 31秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。