C言語なら俺に聞け 163

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん (ワッチョイ 7bba-Lem2)
垢版 |
2024/07/16(火) 22:43:54.18ID:ZrsCjURC0
!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
2024/09/02(月) 23:12:40.71ID:3HuFqT9S0
Nim推しは以前から変なやつ多かったから
2024/09/02(月) 23:28:27.10ID:09ZYUS090
Nim言語の良し悪しは分からんが、メモリ管理に関しては理想的だわ
ムーブ後のオブジェクトにアクセスするとRustだとコンパイルエラーで面倒な事になるけど、Nimは参照カウントを使って解決するので少し遅くなるだけだ
そっちの方が絶対良い
気になる場合は後で直せる
2024/09/03(火) 18:51:27.81ID:xAVNzrUq0
>>33
コンパイルエラー?
2024/09/04(水) 01:03:52.03ID:c5l8yfTZ0
>>34
だからなんだ?
Rustでムーブ後のオブジェクトにアクセスしてみろよ
2024/09/04(水) 09:34:28.92ID:eBGcFHFx0
>>33
どこにコンパイル時期にメモリの不正アクセス検知できるコンパイラーがあるんだよ
便利すぎないか
2024/09/04(水) 09:42:59.71ID:uvDwCGK/0
>>36
ムーブ(所有権の移動)の概念知らない奴かよw
2024/09/04(水) 11:20:54.96ID:yycwJMQK0
時代に取り残されたじじい
2024/09/04(水) 11:26:12.60ID:6FkHz3Id0
今どきのヤングはどの辺を走っているのかな?
40デフォルトの名無しさん (アウアウエー Sa1f-XN8b)
垢版 |
2024/09/05(木) 00:07:48.49ID:/oUqYYg3a
RefCellのborrowとかborrow_mutがCより速い訳がないだろ
2024/09/05(木) 06:20:13.32ID:IMzSmyWL0
アセンブラ使ったことない子供たちにはわからんのだろ
2024/09/05(木) 08:53:17.49ID:oYH6V42M0
Aiの時代にこんなレトロ言語に夢中になってる場合でもないだろ
2024/09/05(木) 09:42:51.26ID:00qJ+IF20
ペイントソフト溢れた時代にエクセルで描いて絶賛される時代。
2024/09/05(木) 13:27:55.60ID:IMzSmyWL0
AIなんて究極的には予備知識なしで使えるようになるもんだろ
いま必死で呪文を覚えてる奴らには気の毒だがw
プログラムの学習はそれとは逆だぞ
2024/09/05(木) 13:41:12.34ID:YoL+MCk60
AIにはアセンブラかCで書かせた方が効率がいいじゃん
2024/09/05(木) 20:45:06.75ID:mduO1G690
今はアニメもCGで作る時代だけど、だからデッサン力なんて不要と言ってるのに近いなw
2024/09/06(金) 02:12:25.16ID:ObPC8Kit0
AIなら直接機械語書けそうだけど最低限人間がコードを読めるようにするためにCで出力するのが流行りそう
2024/09/06(金) 17:06:00.74ID:3sxDLHxZ0
もはやプログラマはAIにどう質問するかだけが求められてる時代
ビックデータが前提なのはわかってるけどchatAIと画像AIはマジでオーパーツだわとても0と1だけで実現されてる技術と思えん・・・
2024/09/06(金) 17:30:18.67ID:bUa4C6AFM
ここはAIの質問スレになる予定です
2024/09/06(金) 17:59:38.15ID:wWap9ofG0
>>48
Cやアセンブラを知らなかったらコンピューター自体が魔法に思えるんだろうなw
2024/09/06(金) 18:14:44.45ID:fzo/g0jk0
プログラム上での比較が、未だに変数2つの比較(if(A=B)とか )しかイメージ出来ないので
AIのアルゴリズムどころか、2つのサイズの違う画像比較ってのさえどうやるのか検討もつかん・・・。
2024/09/06(金) 18:37:17.18ID:4wqfzUPa0
3Blue1BrownJapanのディープラーニング解説動画
https://www.youtube.com/watch?v=tc8RTtwvd5U
現在chapter6まで和訳されてる(本家英語版は7が出た)
2024/09/06(金) 21:13:32.20ID:wWap9ofG0
>>51
引き算してその絶対値が一定以内だったら同じとみなす
if(abs(A-B)<C){…
それぐらいならわかるだろ?
2024/09/06(金) 21:19:53.07ID:eMGejp5m0
点でしか見れない人に面を理解させる手法・・・
2024/09/06(金) 21:46:42.59ID:ObPC8Kit0
この世界もほぼ陽子と中性子と電子だけで出来てるのにこれだけ複雑なんだから0と1だけで複雑な演算出来ても不思議ではない
2024/09/06(金) 21:53:29.16ID:H8MSdYGz0
ようこちゃんとでんこちゃんは知っているけど
中性子って子は知らない
2024/09/06(金) 22:09:25.96ID:aKdHJjI6M
光子ちゃんも忘れないであげて
2024/09/07(土) 00:47:09.38ID:mFTEs+Pq0
0と1だけじゃないけどな
その他に位(くらい)という概念がある
これによって無限の数を表現できる
むしろ位の概念によって数が表現されている
それさえ有れば記号なんて何でもいい
2024/09/07(土) 20:51:59.47ID:XGt+Z3l/0
どこかの国だか村では両手の指の数以上を表現する言葉がないって話をどこかで・・・。
2024/09/07(土) 22:06:43.98ID:GNvzZpYIM
ムカデは100進数で数えている
2024/09/08(日) 00:25:53.15ID:zd6RlSMM0
>>59
位の概念が無いから10までしか数えられない
位を考慮すると両手で1023まで数えられる
2024/09/08(日) 00:30:46.43ID:zd6RlSMM0
指を曲げる伸ばすの2通りとすると1023だが、指を完全に曲げる、伸ばす、半分まで伸ばす(曲げる)の3通りとすると3^10-1=59,048まで表現できるなw
63デフォルトの名無しさん (ワッチョイ 662a-Vk/b)
垢版 |
2024/09/08(日) 07:38:58.99ID:LXYiwE7e0
>>60
ヒトを含めた四肢類は4進法なの?
2024/09/08(日) 10:08:59.05ID:mVbg4wOX0
>>61-62
人差し指と薬指を伸ばして、かつ中指と小指を曲げるのは難易度がやや高いぜ。
(親指を伸ばせば『グワシ』)
2024/09/08(日) 10:25:56.18ID:IhFVsGpe0
グワシは古語
2024/09/08(日) 15:41:04.82ID:aTNFTtUw0
とりあえず、他人の投稿で言ってもいない単語や解釈を勝手に加えてマウント取ろうとするのはどうかと思うぞ。
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);
}
2024/09/09(月) 17:17:50.19ID:JnQxQHVK0
>>68
 char *p = s;
 char *q = t;
 while (*q++ = *p++)

こう書けば通る。何故かはちょっと考えて ;
2024/09/09(月) 17:19:13.64ID:XH4OT6yj0
>>68
s の型は char[5] 、 t の型は char[100] だというのはわかる?
だけど式に出てくる配列は原則として配列の先頭要素を指すポインタ (この場合に型でいえば char*) に型変換される。
変換後に出てくるポインタは rvalue なのでインクリメントの対象に出来ない。

rvalue ってのは式の評価をする間に一時的に生まれて評価が終わったら消えるものなので
仮にインクリメント出来たとしても何にも使えない。

配列が勝手にポインタに変換されるっていうのが変則的で分かり難いポイントだけど
これは C を使ってたら避けようがない。
2024/09/09(月) 18:22:38.82ID:zvC05GrM0
ポインタと同じ表記が使えるだけでポインタに変換されるわけではないぞ老害
2024/09/09(月) 18:25:50.23ID:JnQxQHVK0
 char *s = "hoge";
 char t[100];
 int i = 0;
 while (*(t+i) = *s++)
  i++;

sを配列ではなく、ポインタに変える、
tもポインタにしたいところだが、格納先確保が目的なら
先頭アドレスからのオフセット指定で格納する様に変更
2024/09/09(月) 18:30:55.08ID:D7I9z5W00
それなら while (*(t+i) = *(s+i)) って書くかな
2024/09/09(月) 18:36:50.90ID:JnQxQHVK0
s[]、t[100]と書いたとき、sやtはメモリー上の特定の位置を指す
ラベルのようなものなので書き換える事は出来ない。ポインタ定数とも言う。
一方ポインタ変数は、任意のアドレスを指す変数、変更も操作できる
constとか、突っ込まんでください
2024/09/09(月) 18:57:03.60ID:XH4OT6yj0
>>71
規格には「型変換する」と明瞭に書いてあって変換しないと解釈できる余地はない。
2024/09/10(火) 07:06:02.36ID:fwzKZR690
色々教えてくれてありがとう
s[]の先頭を指すポインタ*sを++で進めることができちゃったら
s[0]もズレちゃうのでだめだってことだよね
そりゃだめだわ
2024/09/10(火) 07:45:50.17ID:ZXVJVLjy0
s[], t[100]; って宣言したなら、s[idx], t[idx] って使おうよ
2024/09/10(火) 08:09:53.27ID:oAzej4EH0
そこはこだわらんでもいいだろ
2024/09/10(火) 09:09:59.70ID:H8O84G940
sやtは constということでもないのか
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とは扱いが違ったんじゃね
2024/09/10(火) 14:04:37.40ID:rqI1GpSt0
lvalue の概念は K&R 1st の頃からあったよ。
lvalue という用語はちょっとどうなの……と思うけど。
Rust だと place と呼んでるみたいだね。
83デフォルトの名無しさん (ワッチョイ eafd-BHET)
垢版 |
2024/09/10(火) 21:10:52.20ID:UL+jlunn0
お前は変な事ばかり言ってるからもう引っ込んどけよ
2024/09/10(火) 21:22:40.00ID:OwUxLa4s0
ポインタそのものを変えないやつと
指す先を変えないやつの書き方で
未だに迷うっていう
2024/09/10(火) 21:35:00.77ID:rqI1GpSt0
キーワードを並べる順序で意味が変わるのは迷うけど
順序をどうならべても良い場合もそれはそれでびっくりする。

int const long foo;

みたいに変数を宣言して良い。
まあそんなことをするやつはいないと思うけど。
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
とも書ける
これが分かれば迷う事は無くなる
2024/09/11(水) 01:20:44.10ID:ZbZmMQbl0
それ前橋氏のポインタ完全制覇で知った
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には実体がない
アドレス定義ラベルでしかない

*ただし完全に最適化されると下も上と同じになる
   
2024/09/11(水) 09:16:47.77ID:IhX3t9qv0
ここでいう sには実体がない、とはどういうことですか?
2024/09/11(水) 09:19:23.27ID:Zm39E+090
大元の質問が >>68 なので低レイヤからの説明はあまり筋が良くないと思う。
エラーメッセージの意味を読み取れるようにならないから。
2024/09/11(水) 09:30:46.32ID:dQ20XCdF0
8ビットCPUのメモリ保護されてない頃だと
配列どころか、プログラムコードも書換できました笑
2024/09/11(水) 09:49:35.14ID:h52e7Ahm0
> sには実体がない、とはどういうことですか?
変数エリアに書き込まれていない数値、データ。
プログラム上で要求された時にコンパイル時や関数によってその都度作られる仕様・・・かな?しらんけど。

>91
>プログラムコードも書換できました
それはむしろ”技術”扱いだったな。
サブルーチンでジャンプ先やIOポートを書き換えて・・・て。
昔はCPU等のバグ利用がテクニックだったけど、今じゃバグの温床、セキュリティホール扱いだね。
93デフォルトの名無しさん (ワッチョイ 1e3e-42jK)
垢版 |
2024/09/11(水) 15:02:12.18ID:DEx1pDDa0
こんだけいて>>77くらいしかまともな回答者がいないとかひどいなあ
2024/09/11(水) 15:25:16.11ID:1n/VD1trM
そんなのこだわっても結局関数の引数で配列型では渡せないんだからその程度は受け入れて慣れたほうがいい
2024/09/11(水) 15:58:54.52ID:dQ20XCdF0
ここは、「聞け」とはあるが、「回答する」とは書いていない
2024/09/11(水) 16:44:23.62ID:+qxKgs2P0
こっちが自然だろ
t[100]を*(t+idx)なんてやる方が何の拘りだよ
2024/09/11(水) 16:55:25.58ID:tx1pt4w10
その程度どっちでもいい
2024/09/11(水) 20:45:08.11ID:l6JSnCmY0
配列は外部リンケージのときも注意が必要なんだよね
あまりそういう使い方しないから、すぐにはピンとこないや
2024/09/11(水) 22:04:51.93ID:+V4MmH6p0
>>93
別にまともでもない
配列で定義してポインタで操作できるのがCの柔軟性だから
idxにこだわると簡単な操作を複雑にしかねない
2024/09/11(水) 23:11:00.81ID:dQ20XCdF0
> while (*(t+i) = *s++)

これは、

> while (*t++ = *s++)
;これがエラーになるのは何故かと言う質問から始まったからです

t++がエラーで、t+iなら大丈夫が理解できれば解決だと思う
ポインタの理解というのは壁にはなりますが、
乗り越えれば意外と簡単です、がんばれ!
2024/09/12(木) 00:58:15.86ID:QGeKjVfA0
>>92 ありがとうございました(sには実態がない)

gcc -S test.c
で .s を出力して眺めてみると、そのような感じになっていました
最適化と、AT&Tのオペランドが逆なのに慣れず読みにくかったですが

"hoge" は「実体」が .data に置かれ、実行時にスタックにコピーされるのかと想像してましたが、実装がどうあれ、スタッフ上に "hoge" を置くための元を実体というのは違うと思いました

実際、"hoge" は .db でアロケートされず、4字は 32ビットの数値定数とされ、スタックに即値で転記されていました(実行時に生成されていました)

# とても伝わりにくいと思いますが…
2024/09/12(木) 08:54:43.60ID:TbaO6N6i0
誰も説明してなかったことに気づいた。
E1[E2] が (*((E1)+(E2))) と等価であるというルールがある。
103デフォルトの名無しさん (ワッチョイ 8a5c-8qrK)
垢版 |
2024/09/12(木) 21:59:57.92ID:m7IlJoP80
それいにしえからのバカ発見器なんだが2024年になってもまだ動いてるとはC言語おそるべし
2024/09/12(木) 23:41:05.77ID:+nQe2m720
次の方どうぞ
2024/09/12(木) 23:43:09.62ID:sEtsUeoh0
>>103
その自由度があるからC++でhtbl["key"]の様な事が出来る
Cじゃ意味ない仕様だけど、禁止する必要も無かろう
2024/09/13(金) 08:23:17.89ID:ykZRrldI0
>>101
"hoge"は長さちょうど32ビットだから即値でスタックに書き込むようになってるということなら
最適化によってそこまで省略されてるわけでsに実体がない件とはあまり関係ないな
最適化オフにするかもっと長い文字列で実験してみては
2024/09/13(金) 09:12:47.27ID:cjEIJ97r0
>>106
ありがとうございます

もう少し正確に書けばよかったのですが、4字と '\0' の2回に分けて転記していました
また、hogeを長くして(10字くらい?)試すと、やはり 4字ずつ整数にパックして即値で転記していました

もっと長大な文字列試せば、別にアロケートされたそれをコピーするコードが吐かれたかもしれませんが、>>92 の指摘通り、実体がなく実行時に生成されることを確認できたとして打ち切ってしまいました
2024/09/13(金) 10:12:57.71ID:9XTDQHQm0
C の仕様は抽象機械の動作として記述される。
抽象機械の動作をどのように実際の機械と対応させるかは自由で、見かけ上の動作が同じならどういう機械語になってもいい。
生成された機械語から言語仕様を理解しようとすべきではないよ。

低レイヤプログラミングするならどう対応付くか知る必要がある場合もあるのは否定しないけど……
2024/09/13(金) 10:23:10.52ID:OBSQyTYbM
その抽象機械の定義はしょせん後付け
c言語のソースから生成されるマシン語の想像が付くようになるのはいいこと
2024/09/13(金) 10:25:26.12ID:y2ap91b60
C言語ハンドコンパイラ
2024/09/13(金) 11:25:36.89ID:9XTDQHQm0
>>109
機械語の想像がつくのが不要とも悪いとも言ってないよ。
そこから言語仕様を理解しようとすべきじゃないと述べてる。
できないから。
2024/09/13(金) 11:46:29.60ID:HT/On1VB0
所詮部外者の推測。
2024/09/13(金) 12:46:10.11ID:CiewPVvpM
今日は患者が多いですね
2024/09/13(金) 12:53:56.59ID:OBSQyTYbM
>>111
無用な心配
Xに溢れてるクソリプと同じ
2024/09/13(金) 13:50:08.30ID:cjEIJ97r0
>>108
ありがとうございます

そもそも >>88 で sの実体がないとはどういうことか、というのが疑問だったためで、言語の仕様(というか実装)がどうかには着目していませんでした

printf("%s\n", s); が .sではputs(s); に置き換えられていたり
そうだよな〜
2024/09/13(金) 13:59:45.58ID:cjEIJ97r0
あー、実装には注目してるのか>自分
2024/09/13(金) 14:32:38.41ID:7dvxgxgq0
この場合に限っては言語仕様としての理屈もあんまり違わんけどな。
ただ、正式な用語を知ってると細かいことを調べやすいみたいなのはあるので便利。
2024/09/13(金) 16:10:44.34ID:HymUJJD5H
gccは配列に確保した短い文字列は最適化無しでもレジスターに載せてしまってるな
ポインター文字列は最適化してもレジスターには載らない
なので配列は配列として使った方が最適化で高速化される可能性があるという事だな
2024/09/13(金) 16:26:39.79ID:7dvxgxgq0
ポインター文字列って変な言葉だな。
この場の造語だと思うけど
char *foo = "bar";
みたいなやつのことだよね?

文字列リテラルは静的記憶域期間 (寿命はプログラムの最初から最後まで) を持つオブジェクト。
どこかにある文字列をポインタで指しているという状況。
そのどこかにある文字は他のどこかから指し示されることもありうるので簡単には消えられない。

その一方で、配列の初期化子は配列を初期化する以外に使われる可能性がない。
120デフォルトの名無しさん (アウアウエー Sa52-t/33)
垢版 |
2024/09/13(金) 16:36:31.22ID:bblj+c3pa
>>93
それのどこがマトモなんだよ

>>94 の言い分の方が正しい
配列型が無いんだから
121デフォルトの名無しさん (アウアウエー Sa52-t/33)
垢版 |
2024/09/13(金) 16:38:54.03ID:bblj+c3pa
>>96
>t[100]を*(t+idx)
t[100]を100[t]
よりはマシ

>>97
だよな
2024/09/13(金) 17:26:56.71ID:HymUJJD5H
>>119
んなこたーない
char foo[] = "hoge";
char* bar = &foo[1]; /* 敢えてずらしてみる */
printf("bar -> %s\n", bar);
で中身は何度も参照されるぞ
gccで試してみたら敢えてずらしてポインターに代入されたとしても、レジスターに文字列を保持したままprintfに渡すというトリッキーなコードが生成されたw
スタックに文字列を書き込んでそのアドレスを渡してるっぽい
2024/09/13(金) 17:45:50.36ID:HymUJJD5H
短い配列文字列をポインターに代入したらレジスターに保持する最適化を諦めるかと思ったら、そうじゃなくて意地でもレジスターに保持したまま処理を進めるgccスゲーよw
clangの場合はポインターも配列も常に静的に文字列を定義したものを使ってた
2024/09/13(金) 18:12:32.57ID:y2ap91b60
最近のCPUはレジスターに文字列格納できるんだな
何バイトくらいなら入るんだろうか
2024/09/13(金) 18:26:19.17ID:HymUJJD5H
gccの場合だと64bitだと8バイトだから最大7文字かなと思ったらレジスターを複数使ってでも載せようとしてたw
取り敢えず50文字まで試したけど全部レジスタに載ってた
でもこの辺はレジスタの空き具合にもよるのか?詳しくは分からん
2024/09/13(金) 18:41:27.03ID:y2ap91b60
何か執念みたいなのを感じました笑
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
2024/09/13(金) 18:59:17.17ID:7dvxgxgq0
>>122
その場合に参照されるのは foo であって、 "hoge" というリテラルではない。
"hoge" は foo を初期化する以外の用途に使われていない。
2024/09/13(金) 20:11:25.22ID:ykZRrldI0
>>127
データセグメントに確保するよりも
コードセグメントに書いたほうがすでにキャッシュに載ってるから高速なのかもな
2024/09/13(金) 20:41:46.32ID:cjEIJ97r0
速度の最適化か、生成されるオブジェクトの小ささかのトレードオフなんだろうね
テスト用のコードは小さいから、後者は気にせずゴリゴリやってるのかな…
2024/09/13(金) 23:38:57.27ID:uRdGeQ4y0
世の中CやめてRustにしろだとか
OpenAIの新AIが競プロで上位1割のプログラマに匹敵とか言うじゃない
今更人間がCを続ける意義ってなんなんだろう
2024/09/14(土) 00:03:48.69ID:UIMFiyQN0
COBOLみたくロストテクノロジーを理解出来る貴重な人になれる
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況