[過去ログ] C言語なら俺に聞け 163 (1002レス)
上下前次1-新
このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
116: 警備員[Lv.1][新芽] (ワッチョイ 1e49-ztXh) 2024/09/13(金)13:59 ID:cjEIJ97r0(3/4) AAS
あー、実装には注目してるのか>自分
117: はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-hr+9) 2024/09/13(金)14:32 ID:7dvxgxgq0(1/3) AAS
この場合に限っては言語仕様としての理屈もあんまり違わんけどな。
ただ、正式な用語を知ってると細かいことを調べやすいみたいなのはあるので便利。
118(1): (JP 0H3e-voeu) 2024/09/13(金)16:10 ID:HymUJJD5H(1/5) AAS
gccは配列に確保した短い文字列は最適化無しでもレジスターに載せてしまってるな
ポインター文字列は最適化してもレジスターには載らない
なので配列は配列として使った方が最適化で高速化される可能性があるという事だな
119(1): はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-IU9Y) 2024/09/13(金)16:26 ID:7dvxgxgq0(2/3) AAS
ポインター文字列って変な言葉だな。
この場の造語だと思うけど
char *foo = "bar";
みたいなやつのことだよね?
文字列リテラルは静的記憶域期間 (寿命はプログラムの最初から最後まで) を持つオブジェクト。
どこかにある文字列をポインタで指しているという状況。
そのどこかにある文字は他のどこかから指し示されることもありうるので簡単には消えられない。
その一方で、配列の初期化子は配列を初期化する以外に使われる可能性がない。
120: (アウアウエー Sa52-t/33) 2024/09/13(金)16:36 ID:bblj+c3pa(1/2) AAS
>>93
それのどこがマトモなんだよ
>>94 の言い分の方が正しい
配列型が無いんだから
121: (アウアウエー Sa52-t/33) 2024/09/13(金)16:38 ID:bblj+c3pa(2/2) AAS
>>96
>t[100]を*(t+idx)
t[100]を100[t]
よりはマシ
>>97
だよな
122(2): (JP 0H3e-voeu) 2024/09/13(金)17:26 ID:HymUJJD5H(2/5) AAS
>>119
んなこたーない
char foo[] = "hoge";
char* bar = &foo[1]; /* 敢えてずらしてみる */
printf("bar -> %s\n", bar);
で中身は何度も参照されるぞ
gccで試してみたら敢えてずらしてポインターに代入されたとしても、レジスターに文字列を保持したままprintfに渡すというトリッキーなコードが生成されたw
スタックに文字列を書き込んでそのアドレスを渡してるっぽい
123: (JP 0H3e-voeu) 2024/09/13(金)17:45 ID:HymUJJD5H(3/5) AAS
短い配列文字列をポインターに代入したらレジスターに保持する最適化を諦めるかと思ったら、そうじゃなくて意地でもレジスターに保持したまま処理を進めるgccスゲーよw
clangの場合はポインターも配列も常に静的に文字列を定義したものを使ってた
124: (ワッチョイ 6663-QZ+t) 2024/09/13(金)18:12 ID:y2ap91b60(2/3) AAS
最近のCPUはレジスターに文字列格納できるんだな
何バイトくらいなら入るんだろうか
125: (JP 0H3e-voeu) 2024/09/13(金)18:26 ID:HymUJJD5H(4/5) AAS
gccの場合だと64bitだと8バイトだから最大7文字かなと思ったらレジスターを複数使ってでも載せようとしてたw
取り敢えず50文字まで試したけど全部レジスタに載ってた
でもこの辺はレジスタの空き具合にもよるのか?詳しくは分からん
126: (ワッチョイ 6663-QZ+t) 2024/09/13(金)18:41 ID:y2ap91b60(3/3) AAS
何か執念みたいなのを感じました笑
127(2): (JP 0H3e-voeu) 2024/09/13(金)18:50 ID:HymUJJD5H(5/5) AAS
スマン…間違えた…orz
正確にはアセンブリコードに書かれてると言うべきだった
movabsq $3833745473465760056, %rdx
movabsq $3978425819141910832, %rax
movq %rdx, 40(%rsp)
movabsq $3544395820347831604, %rdx
movq %rdx, 56(%rsp)
↑こんな感じで文字列が直値で表現されてて、スタックに積んで使ってた
だったら静的に確保した方が速い気がするけど、やっぱりレジスターから直接使う事が有るのか?
取り敢えずコンパイラーが出力するコードに深入りしない方が良いって事は分かったw
128(1): はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-IU9Y) 2024/09/13(金)18:59 ID:7dvxgxgq0(3/3) AAS
>>122
その場合に参照されるのは foo であって、 "hoge" というリテラルではない。
"hoge" は foo を初期化する以外の用途に使われていない。
129: (ワッチョイ 65cd-RtM0) 2024/09/13(金)20:11 ID:ykZRrldI0(2/2) AAS
>>127
データセグメントに確保するよりも
コードセグメントに書いたほうがすでにキャッシュに載ってるから高速なのかもな
130: 警備員[Lv.5][新芽] (ワッチョイ 1e21-ztXh) 2024/09/13(金)20:41 ID:cjEIJ97r0(4/4) AAS
速度の最適化か、生成されるオブジェクトの小ささかのトレードオフなんだろうね
テスト用のコードは小さいから、後者は気にせずゴリゴリやってるのかな…
131: (ワッチョイ fa2d-2PHd) 2024/09/13(金)23:38 ID:uRdGeQ4y0(1) AAS
世の中CやめてRustにしろだとか
OpenAIの新AIが競プロで上位1割のプログラマに匹敵とか言うじゃない
今更人間がCを続ける意義ってなんなんだろう
132(1): (ワッチョイ 714e-/njq) 2024/09/14(土)00:03 ID:UIMFiyQN0(1) AAS
COBOLみたくロストテクノロジーを理解出来る貴重な人になれる
133: はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-hr+9) 2024/09/14(土)00:19 ID:N2YvcTj50(1/14) AAS
低レイヤに関わる資料が C を前提に書かれていたりするのは普通のことなのでたとえ C でプログラミングしなくてもある程度は身に付いてないと困ることはあるだろう。
134(2): (ワッチョイ a6e1-865n) 2024/09/14(土)00:39 ID:0gsw2riP0(1/12) AAS
>>128
初期化する以外に参照されてないってのはおかしいだろ
printfで中身が表示されてんだから
ポインター変数のbar経由で中身を参照してるけど、中身は初期化で渡された文字列そのものだ
そもそもリテラルが参照されてないという言い方もおかしい
リテラルは単なる定数の簡略表記に過ぎず、ソースコード上だけの用語だ
実行時に消えてると言いたいのか?
そんなわけない、全く消えてない
135: (ワッチョイ 6663-QZ+t) 2024/09/14(土)00:51 ID:8t7wdnSS0(1/4) AAS
>>132
CobolやFortranはこれからも生き残るよ
多分
136: (ワッチョイ 2a7c-9vXG) 2024/09/14(土)08:27 ID:QgTfRJpW0(1) AAS
>>134
言ってることが意味不明。
textセグメントとかbssとかdataセグメントとか知らんの?
137(1): はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-IU9Y) 2024/09/14(土)08:59 ID:N2YvcTj50(2/14) AAS
>>134
> printfで中身が表示
意味が解らん。
表示されてる中身というのは foo の中身であってリテラルじゃないだろ。
> リテラルは単なる定数の簡略表記
整数リテラルなどは右辺値だが文字列リテラルに限っては左辺値。
文字列リテラルは実行フェイズにおいてオブジェクトとしての性質を持つということ。 (抽象機械の上では。)
ただし、この文字列リテラルが型変換された結果によって生まれるポインタはアドレス定数の要件を満たす。
138(2): (ワッチョイ a6e1-865n) 2024/09/14(土)10:32 ID:0gsw2riP0(2/12) AAS
>>137
int i = 1;
printf("i -> %d\n", i);
この1は同じ様にリテラル表記以外に参照されてないというのか?
139: はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-IU9Y) 2024/09/14(土)10:49 ID:N2YvcTj50(3/14) AAS
>>138
前述の通り整数リテラルは右辺値 (rvalue)。
文字列リテラルは例外的な存在だ。
まず、 C の用語では「オブジェクト」と「値」は違う意味を持つ。
メモリ上のビットパターンがオブジェクトで、値は式の結果だ。
(規格用語では data storage だがここではあえてカジュアルな用語で言うことにする。)
そして式の結果は lvalue と rvalue に区分される。
オブジェクトに結び付いている値が lvalue だと考えていい。
個々に規定があるので詳細は割愛するが、
式の中で変数名だとか単項 * 演算だとか [] とかがあればそれはメモリ上に存在してるのは明白だろ?
そういうのが lvalue 。
たとえば 1+3+5 みたいな式があれば途中で 4 という値が生じるが、これは「どこ」にある?
場所に結び付いておらず、式が終われば破棄されることになってる。
こういうのが rvalue 。
ちなみに lvalue も rvalue が要求される文脈では rvalue に変換される。 (メモリから値が読みだされる。)
140(1): はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-IU9Y) 2024/09/14(土)12:58 ID:N2YvcTj50(4/14) AAS
>>138
このときの 1 というリテラルは (rvalue の) 1 を返す式で、その値が i にコピーされた後で寿命を終えて消滅する。
printf の引数の i で取り出される 1 は i に入っている 1 であってリテラルの 1 じゃない。
整数リテラルはあくまでも整数を返す (生成すると言ってもいいかも?) 式であって、メモリ上のどこかにあるオブジェクトというわけじゃない。
141(1): (ワッチョイ a6e1-865n) 2024/09/14(土)13:32 ID:0gsw2riP0(3/12) AAS
>>140
1は破棄されて"hoge"は破棄されないんだろ?
だから参照されてんじゃん
142(1): はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-hr+9) 2024/09/14(土)13:40 ID:N2YvcTj50(5/14) AAS
>>141
>>122 の bar が参照しているのは文字列リテラルからコピーされた配列であって文字列リテラルではない。
文字列リテラルが破棄されないこととは独立した話だよ。
143(1): (ワッチョイ a6e1-865n) 2024/09/14(土)13:43 ID:0gsw2riP0(4/12) AAS
>>142
barは配列のコピーじゃないだろ
ポインターなんだから
コピーしてるのはアドレス値だぞ
144: はちみつ餃子◆8X2XSCHEME (ワッチョイ 7932-hr+9) 2024/09/14(土)13:55 ID:N2YvcTj50(6/14) AAS
>>143
そのポインタが指しているという意味で参照してると言ってる。
なにを言いたいんだ?
論点は「配列の初期化子として現れる文字列リテラルは配列の初期化以外に使われる可能性がない」という話だろ。
145(1): (ワッチョイ 6663-QZ+t) 2024/09/14(土)14:05 ID:8t7wdnSS0(2/4) AAS
> char foo[] = "hoge";
> char* bar = &foo[1]; /* 敢えてずらしてみる */
> bar が参照しているのは文字列リテラルからコピーされた配列であって文字列リテラルではない。
説明がよく分からないが、barは、fooではなく、どこかにコピーした別の文字列なり配列を参照していると言うことか?
上下前次1-新書関写板覧索設栞歴
あと 857 レスあります
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ
ぬこの手 ぬこTOP 0.017s