!extend:checked:vvvvv:1000:512
(新スレ立ての際上記コマンドを2行書き込んでください)
C言語の話題のみ取り扱います C++の話題はC++スレへ
質問には最低限の情報(ソース/コンパイラ/OS)を付ける
数行で収まらないソースは以下を適当に使ってURLを晒す
https://paiza.io/
https://ideone.com/
http://codepad.org/
C17
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf
C11
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf
C23 最新ドラフト
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf
C99
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
http://kikakurui.com/x3/X3010-2003-01.html
C FAQ 日本語訳
http://www.kouno.jp/home/c_faq/
JPCERT C コーディングスタンダード
https://www.jpcert.or.jp/sc-rules/
※前スレ
C言語なら俺に聞け 162
https://mevius.5ch.net/test/read.cgi/tech/1698653580/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
探検
C言語なら俺に聞け 163
■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん (ワッチョイ 7bba-Lem2)
2024/07/16(火) 22:43:54.18ID:ZrsCjURC063デフォルトの名無しさん (ワッチョイ 662a-Vk/b)
2024/09/08(日) 07:38:58.99ID:LXYiwE7e0 >>60
ヒトを含めた四肢類は4進法なの?
ヒトを含めた四肢類は4進法なの?
64デフォルトの名無しさん (ワッチョイ bd5f-FAeb)
2024/09/08(日) 10:08:59.05ID:mVbg4wOX065デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/08(日) 10:25:56.18ID:IhFVsGpe0 グワシは古語
66デフォルトの名無しさん (ワッチョイ a510-IFMZ)
2024/09/08(日) 15:41:04.82ID:aTNFTtUw0 とりあえず、他人の投稿で言ってもいない単語や解釈を勝手に加えてマウント取ろうとするのはどうかと思うぞ。
67デフォルトの名無しさん (ワッチョイ a6e0-RtM0)
2024/09/08(日) 23:23:27.00ID:6gnZvy5A0 問題はギャグとしてつまらないという点だ
68デフォルトの名無しさん (ワッチョイ fa2d-2PHd)
2024/09/09(月) 17:06:32.51ID:ft14UVke0 lvalueに関してエラーが出るんだけど、どうしてこれがだめなのかわからないです
#include <stdio.h>
int main()
{
char s[] = "hoge";
char t[100];
while (*t++ = *s++)
;
printf("%s", t);
}
#include <stdio.h>
int main()
{
char s[] = "hoge";
char t[100];
while (*t++ = *s++)
;
printf("%s", t);
}
69デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/09(月) 17:17:50.19ID:JnQxQHVK070はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/09(月) 17:19:13.64ID:XH4OT6yj0 >>68
s の型は char[5] 、 t の型は char[100] だというのはわかる?
だけど式に出てくる配列は原則として配列の先頭要素を指すポインタ (この場合に型でいえば char*) に型変換される。
変換後に出てくるポインタは rvalue なのでインクリメントの対象に出来ない。
rvalue ってのは式の評価をする間に一時的に生まれて評価が終わったら消えるものなので
仮にインクリメント出来たとしても何にも使えない。
配列が勝手にポインタに変換されるっていうのが変則的で分かり難いポイントだけど
これは C を使ってたら避けようがない。
s の型は char[5] 、 t の型は char[100] だというのはわかる?
だけど式に出てくる配列は原則として配列の先頭要素を指すポインタ (この場合に型でいえば char*) に型変換される。
変換後に出てくるポインタは rvalue なのでインクリメントの対象に出来ない。
rvalue ってのは式の評価をする間に一時的に生まれて評価が終わったら消えるものなので
仮にインクリメント出来たとしても何にも使えない。
配列が勝手にポインタに変換されるっていうのが変則的で分かり難いポイントだけど
これは C を使ってたら避けようがない。
71デフォルトの名無しさん (ワッチョイ 9e79-auhz)
2024/09/09(月) 18:22:38.82ID:zvC05GrM0 ポインタと同じ表記が使えるだけでポインタに変換されるわけではないぞ老害
72デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/09(月) 18:25:50.23ID:JnQxQHVK0 char *s = "hoge";
char t[100];
int i = 0;
while (*(t+i) = *s++)
i++;
sを配列ではなく、ポインタに変える、
tもポインタにしたいところだが、格納先確保が目的なら
先頭アドレスからのオフセット指定で格納する様に変更
char t[100];
int i = 0;
while (*(t+i) = *s++)
i++;
sを配列ではなく、ポインタに変える、
tもポインタにしたいところだが、格納先確保が目的なら
先頭アドレスからのオフセット指定で格納する様に変更
73デフォルトの名無しさん (ワッチョイ eaad-Pebh)
2024/09/09(月) 18:30:55.08ID:D7I9z5W00 それなら while (*(t+i) = *(s+i)) って書くかな
74デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/09(月) 18:36:50.90ID:JnQxQHVK0 s[]、t[100]と書いたとき、sやtはメモリー上の特定の位置を指す
ラベルのようなものなので書き換える事は出来ない。ポインタ定数とも言う。
一方ポインタ変数は、任意のアドレスを指す変数、変更も操作できる
constとか、突っ込まんでください
ラベルのようなものなので書き換える事は出来ない。ポインタ定数とも言う。
一方ポインタ変数は、任意のアドレスを指す変数、変更も操作できる
constとか、突っ込まんでください
75はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/09(月) 18:57:03.60ID:XH4OT6yj0 >>71
規格には「型変換する」と明瞭に書いてあって変換しないと解釈できる余地はない。
規格には「型変換する」と明瞭に書いてあって変換しないと解釈できる余地はない。
7668 (ワッチョイ fa2d-2PHd)
2024/09/10(火) 07:06:02.36ID:fwzKZR690 色々教えてくれてありがとう
s[]の先頭を指すポインタ*sを++で進めることができちゃったら
s[0]もズレちゃうのでだめだってことだよね
そりゃだめだわ
s[]の先頭を指すポインタ*sを++で進めることができちゃったら
s[0]もズレちゃうのでだめだってことだよね
そりゃだめだわ
77デフォルトの名無しさん (ワッチョイ 1e6e-Qzc4)
2024/09/10(火) 07:45:50.17ID:ZXVJVLjy0 s[], t[100]; って宣言したなら、s[idx], t[idx] って使おうよ
78デフォルトの名無しさん (ワッチョイ a6b5-RtM0)
2024/09/10(火) 08:09:53.27ID:oAzej4EH0 そこはこだわらんでもいいだろ
80デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/10(火) 10:14:17.88ID:WwqiNfks0 立て札は移動禁止です
81デフォルトの名無しさん (アウアウエー Sa52-t/33)
2024/09/10(火) 13:19:09.36ID:KGjTz1X0a >sやtは const
constっていつからあったか知らんけど
constない頃からsもtも*pや*qとは扱いが違ったんじゃね
constっていつからあったか知らんけど
constない頃からsもtも*pや*qとは扱いが違ったんじゃね
82はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/10(火) 14:04:37.40ID:rqI1GpSt0 lvalue の概念は K&R 1st の頃からあったよ。
lvalue という用語はちょっとどうなの……と思うけど。
Rust だと place と呼んでるみたいだね。
lvalue という用語はちょっとどうなの……と思うけど。
Rust だと place と呼んでるみたいだね。
83デフォルトの名無しさん (ワッチョイ eafd-BHET)
2024/09/10(火) 21:10:52.20ID:UL+jlunn0 お前は変な事ばかり言ってるからもう引っ込んどけよ
84デフォルトの名無しさん (ワッチョイ adba-mB8c)
2024/09/10(火) 21:22:40.00ID:OwUxLa4s0 ポインタそのものを変えないやつと
指す先を変えないやつの書き方で
未だに迷うっていう
指す先を変えないやつの書き方で
未だに迷うっていう
85はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/10(火) 21:35:00.77ID:rqI1GpSt0 キーワードを並べる順序で意味が変わるのは迷うけど
順序をどうならべても良い場合もそれはそれでびっくりする。
int const long foo;
みたいに変数を宣言して良い。
まあそんなことをするやつはいないと思うけど。
順序をどうならべても良い場合もそれはそれでびっくりする。
int const long foo;
みたいに変数を宣言して良い。
まあそんなことをするやつはいないと思うけど。
86デフォルトの名無しさん (ワッチョイ a6ee-865n)
2024/09/10(火) 22:53:26.23ID:BKdRZcpD0 consr char*は本当はchar const*と書くべきなんだよね
これでもコンパイルは通って同じ結果になる
読む時は右から読めばいい
pointer to const char
これだと指す先がconstなのが分かりやすい
ポインター自体をconstにするには
char* constとして、同じく右からconst pointer to charと読む
両方constは
char const* const
となるけど、最初のconstは左に書けるので
const char* const
とも書ける
これが分かれば迷う事は無くなる
これでもコンパイルは通って同じ結果になる
読む時は右から読めばいい
pointer to const char
これだと指す先がconstなのが分かりやすい
ポインター自体をconstにするには
char* constとして、同じく右からconst pointer to charと読む
両方constは
char const* const
となるけど、最初のconstは左に書けるので
const char* const
とも書ける
これが分かれば迷う事は無くなる
87デフォルトの名無しさん (ワッチョイ a6b2-Z1Qu)
2024/09/11(水) 01:20:44.10ID:ZbZmMQbl0 それ前橋氏のポインタ完全制覇で知った
88デフォルトの名無しさん (ワッチョイ a6b5-RtM0)
2024/09/11(水) 08:00:07.84ID:eq6A6T9x0 >>81
アセンブラにして考えるとわかりやすい
char s[] = "hoge";
アセンブラの表現↓
s:
.db "hoge¥0"
char *s = "hoge";
アセンブラの表現↓
s_org:
.db "hoge¥0"
s:
.dw s_org
上の場合書き換えようにもsには実体がない
アドレス定義ラベルでしかない
*ただし完全に最適化されると下も上と同じになる
アセンブラにして考えるとわかりやすい
char s[] = "hoge";
アセンブラの表現↓
s:
.db "hoge¥0"
char *s = "hoge";
アセンブラの表現↓
s_org:
.db "hoge¥0"
s:
.dw s_org
上の場合書き換えようにもsには実体がない
アドレス定義ラベルでしかない
*ただし完全に最適化されると下も上と同じになる
90はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/11(水) 09:19:23.27ID:Zm39E+090 大元の質問が >>68 なので低レイヤからの説明はあまり筋が良くないと思う。
エラーメッセージの意味を読み取れるようにならないから。
エラーメッセージの意味を読み取れるようにならないから。
91デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/11(水) 09:30:46.32ID:dQ20XCdF0 8ビットCPUのメモリ保護されてない頃だと
配列どころか、プログラムコードも書換できました笑
配列どころか、プログラムコードも書換できました笑
92デフォルトの名無しさん (ワッチョイ a510-IFMZ)
2024/09/11(水) 09:49:35.14ID:h52e7Ahm0 > sには実体がない、とはどういうことですか?
変数エリアに書き込まれていない数値、データ。
プログラム上で要求された時にコンパイル時や関数によってその都度作られる仕様・・・かな?しらんけど。
>91
>プログラムコードも書換できました
それはむしろ”技術”扱いだったな。
サブルーチンでジャンプ先やIOポートを書き換えて・・・て。
昔はCPU等のバグ利用がテクニックだったけど、今じゃバグの温床、セキュリティホール扱いだね。
変数エリアに書き込まれていない数値、データ。
プログラム上で要求された時にコンパイル時や関数によってその都度作られる仕様・・・かな?しらんけど。
>91
>プログラムコードも書換できました
それはむしろ”技術”扱いだったな。
サブルーチンでジャンプ先やIOポートを書き換えて・・・て。
昔はCPU等のバグ利用がテクニックだったけど、今じゃバグの温床、セキュリティホール扱いだね。
93デフォルトの名無しさん (ワッチョイ 1e3e-42jK)
2024/09/11(水) 15:02:12.18ID:DEx1pDDa0 こんだけいて>>77くらいしかまともな回答者がいないとかひどいなあ
94デフォルトの名無しさん (ブーイモ MM45-bJfQ)
2024/09/11(水) 15:25:16.11ID:1n/VD1trM そんなのこだわっても結局関数の引数で配列型では渡せないんだからその程度は受け入れて慣れたほうがいい
95デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/11(水) 15:58:54.52ID:dQ20XCdF0 ここは、「聞け」とはあるが、「回答する」とは書いていない
96デフォルトの名無しさん (ワッチョイ 1e45-Qzc4)
2024/09/11(水) 16:44:23.62ID:+qxKgs2P0 こっちが自然だろ
t[100]を*(t+idx)なんてやる方が何の拘りだよ
t[100]を*(t+idx)なんてやる方が何の拘りだよ
97デフォルトの名無しさん (ワッチョイ 5ec2-bJfQ)
2024/09/11(水) 16:55:25.58ID:tx1pt4w10 その程度どっちでもいい
配列は外部リンケージのときも注意が必要なんだよね
あまりそういう使い方しないから、すぐにはピンとこないや
あまりそういう使い方しないから、すぐにはピンとこないや
99デフォルトの名無しさん (ワッチョイ 65cd-RtM0)
2024/09/11(水) 22:04:51.93ID:+V4MmH6p0100デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/11(水) 23:11:00.81ID:dQ20XCdF0 > while (*(t+i) = *s++)
これは、
> while (*t++ = *s++)
;これがエラーになるのは何故かと言う質問から始まったからです
t++がエラーで、t+iなら大丈夫が理解できれば解決だと思う
ポインタの理解というのは壁にはなりますが、
乗り越えれば意外と簡単です、がんばれ!
これは、
> while (*t++ = *s++)
;これがエラーになるのは何故かと言う質問から始まったからです
t++がエラーで、t+iなら大丈夫が理解できれば解決だと思う
ポインタの理解というのは壁にはなりますが、
乗り越えれば意外と簡単です、がんばれ!
>>92 ありがとうございました(sには実態がない)
gcc -S test.c
で .s を出力して眺めてみると、そのような感じになっていました
最適化と、AT&Tのオペランドが逆なのに慣れず読みにくかったですが
"hoge" は「実体」が .data に置かれ、実行時にスタックにコピーされるのかと想像してましたが、実装がどうあれ、スタッフ上に "hoge" を置くための元を実体というのは違うと思いました
実際、"hoge" は .db でアロケートされず、4字は 32ビットの数値定数とされ、スタックに即値で転記されていました(実行時に生成されていました)
# とても伝わりにくいと思いますが…
gcc -S test.c
で .s を出力して眺めてみると、そのような感じになっていました
最適化と、AT&Tのオペランドが逆なのに慣れず読みにくかったですが
"hoge" は「実体」が .data に置かれ、実行時にスタックにコピーされるのかと想像してましたが、実装がどうあれ、スタッフ上に "hoge" を置くための元を実体というのは違うと思いました
実際、"hoge" は .db でアロケートされず、4字は 32ビットの数値定数とされ、スタックに即値で転記されていました(実行時に生成されていました)
# とても伝わりにくいと思いますが…
102はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/12(木) 08:54:43.60ID:TbaO6N6i0 誰も説明してなかったことに気づいた。
E1[E2] が (*((E1)+(E2))) と等価であるというルールがある。
E1[E2] が (*((E1)+(E2))) と等価であるというルールがある。
103デフォルトの名無しさん (ワッチョイ 8a5c-8qrK)
2024/09/12(木) 21:59:57.92ID:m7IlJoP80 それいにしえからのバカ発見器なんだが2024年になってもまだ動いてるとはC言語おそるべし
105デフォルトの名無しさん (ワッチョイ a6ee-865n)
2024/09/12(木) 23:43:09.62ID:sEtsUeoh0106デフォルトの名無しさん (ワッチョイ 65cd-RtM0)
2024/09/13(金) 08:23:17.89ID:ykZRrldI0 >>101
"hoge"は長さちょうど32ビットだから即値でスタックに書き込むようになってるということなら
最適化によってそこまで省略されてるわけでsに実体がない件とはあまり関係ないな
最適化オフにするかもっと長い文字列で実験してみては
"hoge"は長さちょうど32ビットだから即値でスタックに書き込むようになってるということなら
最適化によってそこまで省略されてるわけでsに実体がない件とはあまり関係ないな
最適化オフにするかもっと長い文字列で実験してみては
108はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 65e8-hr+9)
2024/09/13(金) 10:12:57.71ID:9XTDQHQm0 C の仕様は抽象機械の動作として記述される。
抽象機械の動作をどのように実際の機械と対応させるかは自由で、見かけ上の動作が同じならどういう機械語になってもいい。
生成された機械語から言語仕様を理解しようとすべきではないよ。
低レイヤプログラミングするならどう対応付くか知る必要がある場合もあるのは否定しないけど……
抽象機械の動作をどのように実際の機械と対応させるかは自由で、見かけ上の動作が同じならどういう機械語になってもいい。
生成された機械語から言語仕様を理解しようとすべきではないよ。
低レイヤプログラミングするならどう対応付くか知る必要がある場合もあるのは否定しないけど……
109デフォルトの名無しさん (ブーイモ MM45-bJfQ)
2024/09/13(金) 10:23:10.52ID:OBSQyTYbM その抽象機械の定義はしょせん後付け
c言語のソースから生成されるマシン語の想像が付くようになるのはいいこと
c言語のソースから生成されるマシン語の想像が付くようになるのはいいこと
110デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/13(金) 10:25:26.12ID:y2ap91b60 C言語ハンドコンパイラ
111はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 65e8-hr+9)
2024/09/13(金) 11:25:36.89ID:9XTDQHQm0112デフォルトの名無しさん (ワッチョイ a510-IFMZ)
2024/09/13(金) 11:46:29.60ID:HT/On1VB0 所詮部外者の推測。
113デフォルトの名無しさん (ワンミングク MM7a-k+ON)
2024/09/13(金) 12:46:10.11ID:CiewPVvpM 今日は患者が多いですね
114デフォルトの名無しさん (ブーイモ MM45-bJfQ)
2024/09/13(金) 12:53:56.59ID:OBSQyTYbM117はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-hr+9)
2024/09/13(金) 14:32:38.41ID:7dvxgxgq0 この場合に限っては言語仕様としての理屈もあんまり違わんけどな。
ただ、正式な用語を知ってると細かいことを調べやすいみたいなのはあるので便利。
ただ、正式な用語を知ってると細かいことを調べやすいみたいなのはあるので便利。
118デフォルトの名無しさん (JP 0H3e-voeu)
2024/09/13(金) 16:10:44.34ID:HymUJJD5H gccは配列に確保した短い文字列は最適化無しでもレジスターに載せてしまってるな
ポインター文字列は最適化してもレジスターには載らない
なので配列は配列として使った方が最適化で高速化される可能性があるという事だな
ポインター文字列は最適化してもレジスターには載らない
なので配列は配列として使った方が最適化で高速化される可能性があるという事だな
119はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/13(金) 16:26:39.79ID:7dvxgxgq0 ポインター文字列って変な言葉だな。
この場の造語だと思うけど
char *foo = "bar";
みたいなやつのことだよね?
文字列リテラルは静的記憶域期間 (寿命はプログラムの最初から最後まで) を持つオブジェクト。
どこかにある文字列をポインタで指しているという状況。
そのどこかにある文字は他のどこかから指し示されることもありうるので簡単には消えられない。
その一方で、配列の初期化子は配列を初期化する以外に使われる可能性がない。
この場の造語だと思うけど
char *foo = "bar";
みたいなやつのことだよね?
文字列リテラルは静的記憶域期間 (寿命はプログラムの最初から最後まで) を持つオブジェクト。
どこかにある文字列をポインタで指しているという状況。
そのどこかにある文字は他のどこかから指し示されることもありうるので簡単には消えられない。
その一方で、配列の初期化子は配列を初期化する以外に使われる可能性がない。
120デフォルトの名無しさん (アウアウエー Sa52-t/33)
2024/09/13(金) 16:36:31.22ID:bblj+c3pa121デフォルトの名無しさん (アウアウエー Sa52-t/33)
2024/09/13(金) 16:38:54.03ID:bblj+c3pa122デフォルトの名無しさん (JP 0H3e-voeu)
2024/09/13(金) 17:26:56.71ID:HymUJJD5H >>119
んなこたーない
char foo[] = "hoge";
char* bar = &foo[1]; /* 敢えてずらしてみる */
printf("bar -> %s\n", bar);
で中身は何度も参照されるぞ
gccで試してみたら敢えてずらしてポインターに代入されたとしても、レジスターに文字列を保持したままprintfに渡すというトリッキーなコードが生成されたw
スタックに文字列を書き込んでそのアドレスを渡してるっぽい
んなこたーない
char foo[] = "hoge";
char* bar = &foo[1]; /* 敢えてずらしてみる */
printf("bar -> %s\n", bar);
で中身は何度も参照されるぞ
gccで試してみたら敢えてずらしてポインターに代入されたとしても、レジスターに文字列を保持したままprintfに渡すというトリッキーなコードが生成されたw
スタックに文字列を書き込んでそのアドレスを渡してるっぽい
123デフォルトの名無しさん (JP 0H3e-voeu)
2024/09/13(金) 17:45:50.36ID:HymUJJD5H 短い配列文字列をポインターに代入したらレジスターに保持する最適化を諦めるかと思ったら、そうじゃなくて意地でもレジスターに保持したまま処理を進めるgccスゲーよw
clangの場合はポインターも配列も常に静的に文字列を定義したものを使ってた
clangの場合はポインターも配列も常に静的に文字列を定義したものを使ってた
124デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/13(金) 18:12:32.57ID:y2ap91b60 最近のCPUはレジスターに文字列格納できるんだな
何バイトくらいなら入るんだろうか
何バイトくらいなら入るんだろうか
125デフォルトの名無しさん (JP 0H3e-voeu)
2024/09/13(金) 18:26:19.17ID:HymUJJD5H gccの場合だと64bitだと8バイトだから最大7文字かなと思ったらレジスターを複数使ってでも載せようとしてたw
取り敢えず50文字まで試したけど全部レジスタに載ってた
でもこの辺はレジスタの空き具合にもよるのか?詳しくは分からん
取り敢えず50文字まで試したけど全部レジスタに載ってた
でもこの辺はレジスタの空き具合にもよるのか?詳しくは分からん
126デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/13(金) 18:41:27.03ID:y2ap91b60 何か執念みたいなのを感じました笑
127デフォルトの名無しさん (JP 0H3e-voeu)
2024/09/13(金) 18:50:06.89ID:HymUJJD5H スマン…間違えた…orz
正確にはアセンブリコードに書かれてると言うべきだった
movabsq $3833745473465760056, %rdx
movabsq $3978425819141910832, %rax
movq %rdx, 40(%rsp)
movabsq $3544395820347831604, %rdx
movq %rdx, 56(%rsp)
↑こんな感じで文字列が直値で表現されてて、スタックに積んで使ってた
だったら静的に確保した方が速い気がするけど、やっぱりレジスターから直接使う事が有るのか?
取り敢えずコンパイラーが出力するコードに深入りしない方が良いって事は分かったw
正確にはアセンブリコードに書かれてると言うべきだった
movabsq $3833745473465760056, %rdx
movabsq $3978425819141910832, %rax
movq %rdx, 40(%rsp)
movabsq $3544395820347831604, %rdx
movq %rdx, 56(%rsp)
↑こんな感じで文字列が直値で表現されてて、スタックに積んで使ってた
だったら静的に確保した方が速い気がするけど、やっぱりレジスターから直接使う事が有るのか?
取り敢えずコンパイラーが出力するコードに深入りしない方が良いって事は分かったw
128はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/13(金) 18:59:17.17ID:7dvxgxgq0129デフォルトの名無しさん (ワッチョイ 65cd-RtM0)
2024/09/13(金) 20:11:25.22ID:ykZRrldI0 速度の最適化か、生成されるオブジェクトの小ささかのトレードオフなんだろうね
テスト用のコードは小さいから、後者は気にせずゴリゴリやってるのかな…
テスト用のコードは小さいから、後者は気にせずゴリゴリやってるのかな…
131デフォルトの名無しさん (ワッチョイ fa2d-2PHd)
2024/09/13(金) 23:38:57.27ID:uRdGeQ4y0 世の中CやめてRustにしろだとか
OpenAIの新AIが競プロで上位1割のプログラマに匹敵とか言うじゃない
今更人間がCを続ける意義ってなんなんだろう
OpenAIの新AIが競プロで上位1割のプログラマに匹敵とか言うじゃない
今更人間がCを続ける意義ってなんなんだろう
132デフォルトの名無しさん (ワッチョイ 714e-/njq)
2024/09/14(土) 00:03:48.69ID:UIMFiyQN0 COBOLみたくロストテクノロジーを理解出来る貴重な人になれる
133はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-hr+9)
2024/09/14(土) 00:19:19.91ID:N2YvcTj50 低レイヤに関わる資料が C を前提に書かれていたりするのは普通のことなのでたとえ C でプログラミングしなくてもある程度は身に付いてないと困ることはあるだろう。
134デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 00:39:08.66ID:0gsw2riP0 >>128
初期化する以外に参照されてないってのはおかしいだろ
printfで中身が表示されてんだから
ポインター変数のbar経由で中身を参照してるけど、中身は初期化で渡された文字列そのものだ
そもそもリテラルが参照されてないという言い方もおかしい
リテラルは単なる定数の簡略表記に過ぎず、ソースコード上だけの用語だ
実行時に消えてると言いたいのか?
そんなわけない、全く消えてない
初期化する以外に参照されてないってのはおかしいだろ
printfで中身が表示されてんだから
ポインター変数のbar経由で中身を参照してるけど、中身は初期化で渡された文字列そのものだ
そもそもリテラルが参照されてないという言い方もおかしい
リテラルは単なる定数の簡略表記に過ぎず、ソースコード上だけの用語だ
実行時に消えてると言いたいのか?
そんなわけない、全く消えてない
135デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/14(土) 00:51:01.21ID:8t7wdnSS0136デフォルトの名無しさん (ワッチョイ 2a7c-9vXG)
2024/09/14(土) 08:27:14.72ID:QgTfRJpW0137はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/14(土) 08:59:02.76ID:N2YvcTj50 >>134
> printfで中身が表示
意味が解らん。
表示されてる中身というのは foo の中身であってリテラルじゃないだろ。
> リテラルは単なる定数の簡略表記
整数リテラルなどは右辺値だが文字列リテラルに限っては左辺値。
文字列リテラルは実行フェイズにおいてオブジェクトとしての性質を持つということ。 (抽象機械の上では。)
ただし、この文字列リテラルが型変換された結果によって生まれるポインタはアドレス定数の要件を満たす。
> printfで中身が表示
意味が解らん。
表示されてる中身というのは foo の中身であってリテラルじゃないだろ。
> リテラルは単なる定数の簡略表記
整数リテラルなどは右辺値だが文字列リテラルに限っては左辺値。
文字列リテラルは実行フェイズにおいてオブジェクトとしての性質を持つということ。 (抽象機械の上では。)
ただし、この文字列リテラルが型変換された結果によって生まれるポインタはアドレス定数の要件を満たす。
138デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 10:32:56.64ID:0gsw2riP0139はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/14(土) 10:49:21.06ID:N2YvcTj50 >>138
前述の通り整数リテラルは右辺値 (rvalue)。
文字列リテラルは例外的な存在だ。
まず、 C の用語では「オブジェクト」と「値」は違う意味を持つ。
メモリ上のビットパターンがオブジェクトで、値は式の結果だ。
(規格用語では data storage だがここではあえてカジュアルな用語で言うことにする。)
そして式の結果は lvalue と rvalue に区分される。
オブジェクトに結び付いている値が lvalue だと考えていい。
個々に規定があるので詳細は割愛するが、
式の中で変数名だとか単項 * 演算だとか [] とかがあればそれはメモリ上に存在してるのは明白だろ?
そういうのが lvalue 。
たとえば 1+3+5 みたいな式があれば途中で 4 という値が生じるが、これは「どこ」にある?
場所に結び付いておらず、式が終われば破棄されることになってる。
こういうのが rvalue 。
ちなみに lvalue も rvalue が要求される文脈では rvalue に変換される。 (メモリから値が読みだされる。)
前述の通り整数リテラルは右辺値 (rvalue)。
文字列リテラルは例外的な存在だ。
まず、 C の用語では「オブジェクト」と「値」は違う意味を持つ。
メモリ上のビットパターンがオブジェクトで、値は式の結果だ。
(規格用語では data storage だがここではあえてカジュアルな用語で言うことにする。)
そして式の結果は lvalue と rvalue に区分される。
オブジェクトに結び付いている値が lvalue だと考えていい。
個々に規定があるので詳細は割愛するが、
式の中で変数名だとか単項 * 演算だとか [] とかがあればそれはメモリ上に存在してるのは明白だろ?
そういうのが lvalue 。
たとえば 1+3+5 みたいな式があれば途中で 4 という値が生じるが、これは「どこ」にある?
場所に結び付いておらず、式が終われば破棄されることになってる。
こういうのが rvalue 。
ちなみに lvalue も rvalue が要求される文脈では rvalue に変換される。 (メモリから値が読みだされる。)
140はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/14(土) 12:58:36.93ID:N2YvcTj50 >>138
このときの 1 というリテラルは (rvalue の) 1 を返す式で、その値が i にコピーされた後で寿命を終えて消滅する。
printf の引数の i で取り出される 1 は i に入っている 1 であってリテラルの 1 じゃない。
整数リテラルはあくまでも整数を返す (生成すると言ってもいいかも?) 式であって、メモリ上のどこかにあるオブジェクトというわけじゃない。
このときの 1 というリテラルは (rvalue の) 1 を返す式で、その値が i にコピーされた後で寿命を終えて消滅する。
printf の引数の i で取り出される 1 は i に入っている 1 であってリテラルの 1 じゃない。
整数リテラルはあくまでも整数を返す (生成すると言ってもいいかも?) 式であって、メモリ上のどこかにあるオブジェクトというわけじゃない。
141デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 13:32:49.89ID:0gsw2riP0142はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-hr+9)
2024/09/14(土) 13:40:20.14ID:N2YvcTj50143デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 13:43:47.04ID:0gsw2riP0144はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-hr+9)
2024/09/14(土) 13:55:39.65ID:N2YvcTj50145デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/14(土) 14:05:45.99ID:8t7wdnSS0 > char foo[] = "hoge";
> char* bar = &foo[1]; /* 敢えてずらしてみる */
> bar が参照しているのは文字列リテラルからコピーされた配列であって文字列リテラルではない。
説明がよく分からないが、barは、fooではなく、どこかにコピーした別の文字列なり配列を参照していると言うことか?
> char* bar = &foo[1]; /* 敢えてずらしてみる */
> bar が参照しているのは文字列リテラルからコピーされた配列であって文字列リテラルではない。
説明がよく分からないが、barは、fooではなく、どこかにコピーした別の文字列なり配列を参照していると言うことか?
146はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/14(土) 14:20:52.41ID:N2YvcTj50 >>145
bar はどうでもいいよ。 それは要らん間接参照を入れて例としてよくわからんようになってるから
飛び飛びになってる私の書いてることをあらためてまとめると
・ char foo[] = "hoge"; といったような記述があれば "hoge" によって foo を初期化する。
・ このときの文字列リテラル "hoge" は foo を初期化するだけに使われて他からアクセスされる可能性がない。
・ 言語規格の建前上は文字列リテラルの寿命はプログラムの最初から最後までだが……
・ この場合は他からアクセスされる可能性がないから機械語レベルでは文字列リテラルは最適化で消えて (即値としてコードに埋め込んで) も問題にならない。
bar はどうでもいいよ。 それは要らん間接参照を入れて例としてよくわからんようになってるから
飛び飛びになってる私の書いてることをあらためてまとめると
・ char foo[] = "hoge"; といったような記述があれば "hoge" によって foo を初期化する。
・ このときの文字列リテラル "hoge" は foo を初期化するだけに使われて他からアクセスされる可能性がない。
・ 言語規格の建前上は文字列リテラルの寿命はプログラムの最初から最後までだが……
・ この場合は他からアクセスされる可能性がないから機械語レベルでは文字列リテラルは最適化で消えて (即値としてコードに埋め込んで) も問題にならない。
147デフォルトの名無しさん (ブーイモ MM0a-bJfQ)
2024/09/14(土) 16:37:38.90ID:kHQOYHTcM148はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-hr+9)
2024/09/14(土) 16:47:20.53ID:N2YvcTj50149デフォルトの名無しさん (ワッチョイ 8af5-/VPw)
2024/09/14(土) 17:01:46.57ID:5H/bnNk90 最適化でどうなるかを考えながらC書くくらいならもうアセンブリ書いたほうが良いと思う
150デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 17:07:34.51ID:0gsw2riP0 >>146
はちみつは文字列リテラルがアセンブリソースの段階で"hoge"と書かれてなければ消えてると思ってんだなw
例え命令コードの即値で書かれていても消えてる訳じゃないからー!残念!
だから話が噛み合わなかったんだw
まぁ強いて言えば、最適化でデータの表現法方を変えても構わないって言えば良い
はちみつは文字列リテラルがアセンブリソースの段階で"hoge"と書かれてなければ消えてると思ってんだなw
例え命令コードの即値で書かれていても消えてる訳じゃないからー!残念!
だから話が噛み合わなかったんだw
まぁ強いて言えば、最適化でデータの表現法方を変えても構わないって言えば良い
151デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 17:14:48.19ID:0gsw2riP0 x = 1; ← 最適化で消えても構わない
x = 2;
最適化で消えても構わないってこういうことを言うんだよ
char foo[] = "hoge";
"hoge"は消えて良い訳ないだろw
gccは実際、命令コードに文字列を埋め込んでスタックに生成してるが、その文字列はポインター変数を使えば参照可能だ
x = 2;
最適化で消えても構わないってこういうことを言うんだよ
char foo[] = "hoge";
"hoge"は消えて良い訳ないだろw
gccは実際、命令コードに文字列を埋め込んでスタックに生成してるが、その文字列はポインター変数を使えば参照可能だ
152はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/14(土) 17:26:48.38ID:N2YvcTj50153はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/14(土) 17:33:13.32ID:N2YvcTj50 >>151
> 参照可能だ
その時参照してるのはスタック上にある配列であって、文字列リテラルではないってのを俺は何度書けばいいんだ?
文字列リテラルは本来は「プログラムの開始から終わりまでの寿命を持つオブジェクト」としてあらねばならないのが、
実際には文字列リテラルではない形になってることを「消えてる」と表現したのは確かに微妙な表現だったかもしれないが、
有るべき場所から消えてるんだからそんくらいわかるだろ。
そもそも最初は char* foo = "hoge"; との対比で言ってたんだから。
> 参照可能だ
その時参照してるのはスタック上にある配列であって、文字列リテラルではないってのを俺は何度書けばいいんだ?
文字列リテラルは本来は「プログラムの開始から終わりまでの寿命を持つオブジェクト」としてあらねばならないのが、
実際には文字列リテラルではない形になってることを「消えてる」と表現したのは確かに微妙な表現だったかもしれないが、
有るべき場所から消えてるんだからそんくらいわかるだろ。
そもそも最初は char* foo = "hoge"; との対比で言ってたんだから。
154デフォルトの名無しさん (ワッチョイ 8a56-/VPw)
2024/09/14(土) 18:13:05.20ID:5H/bnNk90 はちみつ餃子の説明はたぶん、C++ の考え方が混ざっていないか
C で配列の初期化子に文字列リテラルが書けるのはあくまで文字列リテラル限定であって、それは式として扱われるのではなく、lvalue も rvalue もクソもないということだと思うが
C で配列の初期化子に文字列リテラルが書けるのはあくまで文字列リテラル限定であって、それは式として扱われるのではなく、lvalue も rvalue もクソもないということだと思うが
155はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-IU9Y)
2024/09/14(土) 18:35:19.29ID:N2YvcTj50156デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 18:53:38.72ID:0gsw2riP0 >>153
その配列に格納されているデータが文字列リテラルから生成された文字列(の実体)だろ
厳密に言いたいなら、文字列リテラルはコンパイル時に存在さえしてれば良いものなんだよ
何しろ「リテラル」だから
それを生存期間だの実行時の実体とごっちゃにしてるから訳分かんないことになんだよ
コンパイル時にさえ存在してれば良いという事を実行時には消えてても良いとか言っちゃってんでしょ?
その配列に格納されているデータが文字列リテラルから生成された文字列(の実体)だろ
厳密に言いたいなら、文字列リテラルはコンパイル時に存在さえしてれば良いものなんだよ
何しろ「リテラル」だから
それを生存期間だの実行時の実体とごっちゃにしてるから訳分かんないことになんだよ
コンパイル時にさえ存在してれば良いという事を実行時には消えてても良いとか言っちゃってんでしょ?
157デフォルトの名無しさん (ワッチョイ a6e1-865n)
2024/09/14(土) 19:03:33.67ID:0gsw2riP0 char foo[] = { 'h', 'o', 'g', 'e', 0 };
文字列リテラルは↑のシンタックスシュガーだ
初期化子は消えても構わないのか?
初期化子が生成した文字列は参照出来ないと言うのか?
文字列リテラルは↑のシンタックスシュガーだ
初期化子は消えても構わないのか?
初期化子が生成した文字列は参照出来ないと言うのか?
158デフォルトの名無しさん (ワッチョイ 8a56-/VPw)
2024/09/14(土) 19:10:37.88ID:5H/bnNk90 >>155
https://en.cppreference.com/w/c/language/array_initialization
ここ参考にしてたから文法定義の時点で式じゃないと思ってたけど、ちゃんと規格上は式としてのパースではあったね、すまない
改めて C99(でいいんだよね、6.7.8 ってことは)の draft 読んでみたけど、文字列リテラルで初期化できるのは 6.7.8.14,15 で特殊に定義された意味論であって、やっぱり式扱いじゃないんじゃないかね
https://en.cppreference.com/w/c/language/array_initialization
ここ参考にしてたから文法定義の時点で式じゃないと思ってたけど、ちゃんと規格上は式としてのパースではあったね、すまない
改めて C99(でいいんだよね、6.7.8 ってことは)の draft 読んでみたけど、文字列リテラルで初期化できるのは 6.7.8.14,15 で特殊に定義された意味論であって、やっぱり式扱いじゃないんじゃないかね
159はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 7932-hr+9)
2024/09/14(土) 19:58:20.45ID:N2YvcTj50 >>154
結果的な挙動からするとどっちでも良いから書いてないだけかも。
結果的な挙動からするとどっちでも良いから書いてないだけかも。
160デフォルトの名無しさん (ワッチョイ 6663-QZ+t)
2024/09/14(土) 20:16:47.07ID:8t7wdnSS0 皆拘らずに使っているのに言うのもあれなんだが
C言語にはC++で言う参照はありません
C言語にはC++で言う参照はありません
161デフォルトの名無しさん (ワッチョイ a6b2-Z1Qu)
2024/09/14(土) 21:01:12.02ID:NQ2pFzob0 hogeは破棄されないって一人がんばってるID:0gsw2riP0を救済して差し上げたいが……自分も完全にわかってないのでできない。
162デフォルトの名無しさん (ワッチョイ 65cd-RtM0)
2024/09/14(土) 21:04:22.62ID:tDLmxNl+0 実在するのはfoo[]だけで
文字列"hoge"は破壊どころか最初からあっても無くてもいいというのがここまでにわかったことだろ
文字列"hoge"は破壊どころか最初からあっても無くてもいいというのがここまでにわかったことだろ
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 習政権、高市首相への態度硬化 台湾有事発言で連日非難 中国 ★11 [ぐれ★]
- 国内ホテル、既にキャンセルも 訪日客関連業界、事態見守る ★3 [蚤の市★]
- 日本損失1.7兆円に修正 中国渡航自粛の影響試算 [蚤の市★]
- 橋下徹氏 外務省幹部の訪中受け「口だけ番長」へ痛烈指摘 「喧嘩は日本の完敗…なんとかっこ悪い日本か」 [冬月記者★]
- 【外国人問題】小野田紀美担当相「不法就労や不法滞在は許さない」 [シャチ★]
- 【野球】井端監督 大谷翔平、山本由伸らのWBCへの参加 「1日も早く返事ほしい」「待っててといっても、国内組が遅くなってしまう」★3 [冬月記者★]
- 千晴おはよう
- 【実況】博衣こよりのえちえち朝こよ🧪
- 中国「高市が頭を下げて謝罪しない限り、絶対に許さない」 [329329848]
- 🏡
- 「これが完成された醜い姿である>>1」←これなに?
- 安倍晋三の遺産、日銀ETF売却終了予定は2138年 [115996789]
