C言語なら俺に聞け 152

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん (アウアウウー Sa4f-7DQ/)
垢版 |
2019/06/17(月) 18:27:10.41ID:3L1/L9kLa
!extend:checked:vvvvv:1000:512
C言語の話題のみ取り扱います C++の話題はC++スレへ
質問には最低限の情報(ソース/コンパイラ/OS)を付ける
数行で収まらないソースは以下を適当に使ってURLを晒す
https://paiza.io/
https://ideone.com/
http://codepad.org/

C11
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.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/
-
VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured
※前スレ
C言語なら俺に聞け 151
https://mevius.5ch.net/test/read.cgi/tech/1554171817/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured
220デフォルトの名無しさん (ワッチョイ 6f02-ttyE)
垢版 |
2019/07/07(日) 18:03:14.45ID:XjejoYnQ0
>>219
それ顔文字っぽいよね。
221デフォルトの名無しさん (ワッチョイ 6f02-ttyE)
垢版 |
2019/07/07(日) 18:04:40.15ID:XjejoYnQ0
>>216
うちのポインタは8バイトだ。
2019/07/07(日) 19:09:15.76ID:bN7H9WWH0
配列はポインタのシンタックスシュガーでしかない
ポインタは何でも許されるが配列は操作が簡略化と同時に制限されてる
2019/07/07(日) 19:31:01.29ID:wvjux2100
>>222
配列名は定数扱いのポインタですね
しかし、配列だけに許される簡素化ってなんですか?
2019/07/07(日) 19:32:54.23ID:bN7H9WWH0
>>223
配列は宣言した瞬間に領域が確保されてるだろ
2019/07/07(日) 19:33:00.70ID:SGQz+b0c0
>>222
x[-1]、これも許されるんだよな
2019/07/07(日) 20:07:07.70ID:OUCQisjNM
int a[1];

int *a;
a=(int *)malloc(sizeof(int));
の違いって何?
2019/07/07(日) 20:12:27.77ID:0lH1eUtNd
>>226
前者はスタックか静的領域に確保される。後者はヒープに確保される。前者はスコープを抜けると自動で解放。後者は解放しないとメモリーリークする。
2019/07/07(日) 20:15:53.10ID:OUCQisjNM
>>227
ということは配列ってメモリのことよく分からない初心者プログラマ以外には無用の長物なん?
解放漏れの考慮以外でわざわざ配列使うメリットってあるの?
2019/07/07(日) 20:17:35.62ID:bN7H9WWH0
>>228
寧ろ配列で済むのにポインタを使う意味がないぞ
2019/07/07(日) 20:18:55.18ID:JhpdhjN90
>>228
繰り返し(iteration)の処理で連続データを処理・制御するときに配列がないと困る。
2019/07/07(日) 20:29:34.92ID:OUCQisjNM
>>229-230

int a[3];
for(int i=0;i<3;i++) a[i] = 0;

int *a;
a=(int *)malloc(sizeof(int * 3));
for(int i=0;i<3;i++) *(a+i) = 0;

これとこれだと違うの?
ポインタだとchar型の時とか文字列代入出来るし
上位互換な気がするんだけど。
2019/07/07(日) 20:32:06.26ID:JhpdhjN90
>>231
sizeof(int) * 3の間違い。
ヒープだと可能なかぎり自由に実行時にサイズを決められる。
2019/07/07(日) 20:34:52.90ID:JhpdhjN90
配列のサイズが決まるのはコンパイル時だ。
2019/07/07(日) 20:36:22.20ID:bN7H9WWH0
>>231
前者の方が簡潔だし
書かなくていい確保・開放処理は避けるものだ

パフォーマンスも配列の方が上
235デフォルトの名無しさん (ワッチョイ 6352-nrJI)
垢版 |
2019/07/07(日) 20:36:48.46ID:HZba7DSz0
>>228
自分で書いたんだから分かると思うけど、言語構造の話でも>>226の場合は記述量で配列の方が楽だし、読む側もひと目でわかるじゃん。
236デフォルトの名無しさん (ワッチョイ 6352-nrJI)
垢版 |
2019/07/07(日) 20:37:18.16ID:HZba7DSz0
かぶった
2019/07/07(日) 20:50:54.62ID:OUCQisjNM
じゃあ配列は、ポインタの一部機能を制限して使いやすさの向上を図ったものという認識でいいの?
それとも生まれも育ちも全く別の概念?

何か、今やってるcの教材が、まず最初に配列を使ってプログラム書いて、
次の章でポインタ出てきて、今まで配列使って書いた奴をポインタで書き変えろみたいな例題ばっかりだから
だったら最初から配列いらなくない?と思ってしまいました。
2019/07/07(日) 20:52:43.83ID:JhpdhjN90
実用的なプログラム書いてたら、そのうちわかる。心配要らない。
2019/07/07(日) 21:00:11.30ID:OUCQisjNM
分かりました。unionもわざわざこんなの使わずstruct使えばよくねって思うけどそういうもんだと今は思っときます。
2019/07/07(日) 22:02:44.50ID:o4vR1s03a
>>237
むしろ、何故ポインタが不要だと思わんのか謎だわ
2019/07/07(日) 22:15:20.04ID:2f8BNWqD0
なぜopenとfopenの二つのファイルアクセス手段が用意されているのか。
2019/07/07(日) 22:18:01.98ID:wvjux2100
>>241
open() は OS が提供するシステムコールそのもの
fopen() はライブラリ関数であり open() をラップして「使いやすくした」(本当か?)もの
243デフォルトの名無しさん (ワッチョイ 6f02-ttyE)
垢版 |
2019/07/07(日) 23:10:44.83ID:XjejoYnQ0
>>242
バッファっリングしてくれるとか、fprintf()もあったりしてテキストをフォーマットして出力するのも楽というのがある。
2019/07/07(日) 23:15:22.66ID:o4vR1s03a
Cライブラリとしてはfopenしかないわけだけど、正直あんまり便利じゃないよな。
2019/07/07(日) 23:16:29.46ID:wvjux2100
>>243
バッファリングはね…バッファリングは今は大部分 OS が抱いているものなんじゃないかな…アプリケーションが各々のユーザーランドに抱いていてメリットがあるのかな…
246デフォルトの名無しさん (ワッチョイ 6f02-ttyE)
垢版 |
2019/07/07(日) 23:34:13.80ID:XjejoYnQ0
>>245
ま、そうだけどね。Cってそういう今時のちゃんとしたOSのないところや完全にOSなし環境用のプログラム作るのにも使われるし、ああいうライブラリはあってもいいと思う。

まあしかしちょっと古くなった感はあるのでリニューアルしても良いんじゃないかとは思うけどね。てか、最低でも標準ライブラリなのにセキュリティーホール作ってしまうようなのは廃止した方が良いよな。
2019/07/07(日) 23:42:46.95ID:sq3gNEgUd
システムコール自体相当重いから、OS呼び出す回数減らすためのバッファリングだろ
2019/07/07(日) 23:47:08.94ID:YcHC3knN0
入出力バッファリングしてくれるファイルシステムなんてあるか?
ジャーナリングと勘違いしてるんだろ
2019/07/07(日) 23:54:40.74ID:sq3gNEgUd
しない方が珍しくね?
writeしたらディスク書き込み完了するまで次がブロックするとか?
2019/07/07(日) 23:59:57.04ID:YcHC3knN0
それジャーナル制御の話だろ
2019/07/08(月) 00:13:01.27ID:cSAl/tEC0
バッファリングとキャッシュの区別が…。
2019/07/08(月) 00:15:59.34ID:+tWapxmU0
>>248>>245へのレスな
バッファリングはアプリの仕事
2019/07/08(月) 00:21:05.88ID:G56xs+BGM
>>240
char *str;
str = "abc\n";
が許されるから。
配列に文字列を代入出来ないのが不便

>>241
それ言うならfopenとfopen_sの方が意味分からんね
VS使ってたら書き換えろと警告出してくるわ、書き換えたら引数の取り方違うとかいうクソ仕様だし
2019/07/08(月) 00:29:20.86ID:EniIIYRYa
>>253
そりゃ、現実としてそういう建て付けになってんだから使うよ。
でも文字列だったら最初からもうちょっと抽象的な操作の方がいいわ。ポインタ使いたかったら&つけてもいいんだし。
255デフォルトの名無しさん (ワッチョイ 6f02-ttyE)
垢版 |
2019/07/08(月) 00:44:01.80ID:YBWHLZTU0
>>253
一応初期化の時だけ char s[] = "..."; って書き方できるけどね。これは初期化だけの特別な書き方だな。
2019/07/08(月) 01:20:48.92ID:6nQUGxHg0
OSによっては遅延書き込みってしているだろう
257デフォルトの名無しさん (ワッチョイ 6f02-ttyE)
垢版 |
2019/07/08(月) 02:05:54.23ID:YBWHLZTU0
やってるな。外付けのHDD付けた時なんかはするかしないか設定できたりして。
2019/07/08(月) 08:34:21.82ID:IKtCR6xL0
DOS時代、ディスクキャッシュはドライバーが必要だったな。
2019/07/08(月) 08:57:53.53ID:YymrlAAVd
str[9]="おはよう"
str[9]={'お','は','よ','う'}

こうやってまとめて配列に日本語を入れるのは出来るんだけど「お」、「は」、「よ」、「う」と一文字ずつ入れることって出来ますか?
英語ならstr[0]=…、str[1]=…って済むけど
260デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/08(月) 09:43:06.34ID:tzeJFuHla
>>259
> こうやってまとめて配列に日本語を入れるのは出来るんだけど

え?できる?

>「お」、「は」、「よ」、「う」と一文字ずつ入れることって出来ますか?

wchar_t 型を使ってL付けたらできないか?
2019/07/08(月) 09:53:54.58ID:jiAfHW5M0
要素数を明示してるので、文中の代入ではなく、初期化のときの話だろうとは予測できるが
「入れる」というのは、代入を連想させるので、うまい言い回しではないかもね
2019/07/08(月) 11:00:59.71ID:sWBK4Oik0
>>253
関係ないけどconst違反だね
そのケースだけ特別に見逃すことになってるけど

>>255
その書き方はK&Rでは静的記憶域期間にのみ許されていた
なぜだかわかるか?
263デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/08(月) 11:23:23.17ID:tzeJFuHla
>>262
そうだったっけ?そうだったような気もするが。

なかったのは自動変数だと毎回コピーすることになって無駄だからかな?
2019/07/08(月) 11:25:22.35ID:Y+Xu67y40
>>262
初回のみ限定警告100%オフ! 送料無料! だからね
いちおう違反ではないことになってる
2019/07/08(月) 11:45:28.78ID:IKtCR6xL0
>259
>str[9]={'お','は','よ','う'}
マルチバイト文字をこう書く時はエンディアンにも気をつけないとね。
266デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/08(月) 12:17:44.27ID:tzeJFuHla
>>265
てか、それできる?
2019/07/08(月) 12:23:54.16ID:sWBK4Oik0
>>263
memcpyみたいのは言語自体に組み入れるべき機能ではないという判断だ
俺は今でもそう思っている
2019/07/08(月) 12:29:40.10ID:SgFxP6hn0
思ってるって……
じゃK&Rにはwhyは書いてないってこと?

なんでお前の脳みその中身を当てこしなきゃいけねーんだ
バカかこいつ?
2019/07/08(月) 12:30:19.48ID:sWBK4Oik0
>>265
エンディアンが同じでも解釈が違うことがあるぞ
printf("%x %x", 'あ', L'あ');
bcc32: a082 3042
cl: 82a0 3042
gcc: error
2019/07/08(月) 12:31:09.46ID:sWBK4Oik0
>>267
じゃあ言い直そう
- 思っている
+ 賛成している
2019/07/08(月) 12:31:47.98ID:sWBK4Oik0
くそ、安価ミスとは俺としたことが
- >>267
+ >>268
272デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/08(月) 13:00:33.95ID:tzeJFuHla
>>267
なるほど。
2019/07/08(月) 13:43:50.72ID:IKtCR6xL0
>266
どのあたりに疑念を持ってるの?
274デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/08(月) 13:58:51.22ID:tzeJFuHla
>>273
'あ' みたいなのは char じゃないから少なくとも警告出そうな感じするんだが。
2019/07/08(月) 14:09:16.87ID:IKtCR6xL0
int Code='ABCD';
なんて書き方できるから文字列はOK。(Code=0x41424344; と解釈)

全角文字の解釈はコンパイラ次第。unicodeやutf-8対応なら問題ないと思う。
S-JISはよく"\"が含まれる文字で誤作動起こすけど。
2019/07/08(月) 14:54:14.01ID:jiAfHW5M0
C99 6.4.4.4 Character constants で
 character-constant:
  'c-char-sequence'
  L'c-char-sequence'
 c-char-sequence:
  c-char
  c-char-sequence c-char
こうなってて文法的には 'ABCDEF' は許されるんだな ちょっと意外
2019/07/08(月) 15:31:05.17ID:sWBK4Oik0
>>275
printf("%x", Code);
bcc32: 44434241
cl: 41424344
gcc: 41424344
2019/07/08(月) 15:37:58.06ID:u+KjwOdz0
処理系定義の動作だから移植性は落ちるよね
2019/07/08(月) 20:12:45.44ID:84rxMJ1M0
文字定数は
Cではint型
C++ではchar型
2019/07/08(月) 20:54:00.78ID:ibRWBgM50
int *ptr;

↑なんですが、「int型のポインタ変数ptr」、それとも「int *型のポインタ変数ptr」のどちらでしょうか?
2019/07/08(月) 20:55:50.12ID:Fr0SEB8b0
int*型の変数
2019/07/08(月) 21:09:00.76ID:ibRWBgM50
>>281
読み方としては
int (イント) * (ポインタ) 型の変数
でしょうか

「ポインタ変数」と言った場合は「* (ポインタ)変数」という捉え方でいいのでしょうか?
「ポインタ」と言った場合に「*」を指すのは普通ですか?
2019/07/08(月) 21:12:57.52ID:qs7HTSo50
>>282
好きなように把握すればよい、しかし int * の使われ方は決まっているのだから、それがすんなりできるかどうかが問題
2019/07/08(月) 21:24:04.62ID:/2nq94DTa
pointer to int
285デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/08(月) 21:42:19.26ID:prK3AyGza
>>280
Cの場合は変数に*がくっついた形で宣言されていると考えた方が良い。というのは int *a, b; と書いた場合に a は int * 型だが b は int 型になるからだ。
2019/07/08(月) 22:54:53.21ID:ibRWBgM50
なんとなくわかりました
ありがとうございました
2019/07/09(火) 00:31:35.20ID:L+Vy/ftS0
規格書には
pointer to a character type
pointers to structure types
という文が頻繁に出てきますね
日本語で言ったら「char型へのポインタ」のほうが「charのポインタ型」より正しい気がします
>>284さんのpointer to intは日本語なら「int型へのポインタ」ですね

と思ったんですが規格書には
pointer type
も出てくるので、どっちでもいいということでしょうか
つまり「char型へのポインタ」=「charのポインタ型」ということになりますが
2019/07/09(火) 02:08:12.29ID:Mm2yqLXca
変数の宣言と型の宣言が同じ形というCの事情もありそうだが、そこは曖昧だと思うね。
アップキャストしたら単にポインタだし、ポインタ型と言う場面もあるだろう。

これいいね
https://cdecl.org/
289デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/09(火) 09:14:08.91ID:gdYXIa6pa
typedef char *pchar; とすると pchar 型は「charのポインタ型」というとにはなる。
2019/07/09(火) 11:14:54.62ID:L+Vy/ftS0
ということはどっちでもいいんですね
2019/07/09(火) 11:27:52.60ID:knKJba5J0
気にしたことが無いくらいどうでもいい話。
2019/07/09(火) 12:21:07.04ID:J4x6YR7aa
引数のvoidが一体なんなのか考える方が有意義
2019/07/09(火) 12:41:16.87ID:jbK1WB2u0
引数なしの関数を書くときはvoidと書く

以上
2019/07/09(火) 12:59:36.67ID:PyDbCO5q0
voidって引数じゃないの?
2019/07/09(火) 15:08:36.62ID:jbK1WB2u0
引数に予約語使えるの?
2019/07/09(火) 15:44:50.86ID:+qcz+46H0
some_type foo() と戻りがあるのに、その戻りを捨てる意図で
(void)foo(); と呼び出すコードを見たことがあるような気がするが C++ かもしれん

最適化の際にうまいことしてくれるのを期待してるのかしら
2019/07/09(火) 15:55:38.40ID:td6qAd7k0
>>296
コンパイラかコードチェッカーのwarning抑止のためじゃないかな
2019/07/09(火) 16:02:30.30ID:+dEKq4+ba
Cでも使える。
一度も使ってない引数変数があるとか、関数の戻り値を使っとらんとかで警告が出る場合にくっつけるのが主だと思う。
299デフォルトの名無しさん (ワッチョイ cf02-4kw8)
垢版 |
2019/07/09(火) 16:03:09.93ID:NP6oYl9g0
> 引数なしの関数を書くときはvoidと書く
プロトタイプじゃなかったっけ
300デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/09(火) 16:07:01.41ID:gdYXIa6pa
>>299
プロトタイプと違ったらエラーになる。
2019/07/09(火) 16:20:41.31ID:+qcz+46H0
>>297-298
なるほど、警告避けかー

引数に対してのは
callback 関数として、引数の型&数は限定されてるけど
実装時には一部の引数を使わずに実装できちゃうときに発生しそうね

void foo(int arg1, int arg2)
{
 /* 色々書くけど arg2 は使わない: callback 関数の都合で引数の型と数は変えられん */
 (void)arg2;
}
2019/07/09(火) 17:10:50.55ID:NP6oYl9g0
>>299
これ OKでしょ
int func(void);
int func()
{
return 0;
}
2019/07/09(火) 17:12:50.99ID:NP6oYl9g0
アンカミスった >>300
2019/07/09(火) 17:17:21.63ID:+qcz+46H0
>>302 のは 非ANSI の K&Rフォームで警告されるんじゃ

引数有りの記述では
 int func(int);
 int func(a)
 int a;
 { return 0; }
と等価
2019/07/09(火) 17:26:13.08ID:jbK1WB2u0
>>302
これアウトでしょ
int func(void);
int func()
{
return 0;
}

func(hoge);
2019/07/09(火) 17:28:26.22ID:PyDbCO5q0
>>302
VCだと
> warning C4255: 'func' : 関数プロトタイプがありません : '()' を '(void)' に変換します。
って警告出て、関数部分の引数を変えてしまってる
2019/07/09(火) 17:41:06.68ID:3UBru1uA0
>>302
おまえさん、自分のところで動作確認してるか? でたらめこくな
2019/07/09(火) 17:43:09.00ID:8Y9GhXx/M
char *p;
p = "str1";
p = "str2";

こんな風に文字列リテラルのポインタを付け替える時に前の文字列リテラルのメモリ領域を解放するにはどうすればいいの?
2019/07/09(火) 17:49:15.98ID:PyDbCO5q0
>>308
静的領域に確保しているから解放は無理
2019/07/09(火) 17:59:43.14ID:3UBru1uA0
exit関数を呼び出せば解放できるね
2019/07/09(火) 18:21:06.36ID:NP6oYl9g0
X 3010:2003 では

6.7.5.3 関数宣言子(関数原型を含む)
「並びの中の唯一の項目が void 型で名前のない仮引数であるという特別な場合,関数が仮引数をもたないことを指定する。」

6.9.1 関数定義
typedef int F(void);
F f, g;
int f(void) { /*... */ } // 正
int g() { /*... */ } // 正

という訳で
int func(void); /* prototype */
int func() /* definition */
{
return 0;
}
どこかまちがっているか
2019/07/09(火) 18:28:37.94ID:8Y9GhXx/M
>>309
まじですか。じゃあこのような書き方してたらいずれクラッシュするってことですか?

char *p;
while(1) {
//何かの処理
p = "hoge";
}
2019/07/09(火) 18:36:42.49ID:lRtOoeh80
それは同じ"hoge"のアドレスがロードされるだけ
文字列リテラルのポインタ扱うならconst char *使いなされ
314デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/09(火) 18:43:38.45ID:gdYXIa6pa
>>312
文字列の定数は静的な領域に作られるだけで実行時に動的に作られたりしないのでそれは問題なし。
315デフォルトの名無しさん (アウアウウー Sa67-ze1x)
垢版 |
2019/07/09(火) 18:46:20.39ID:gdYXIa6pa
あ、でも、定数でなくても同じか。単にポインタ代入してるだけだもんな。
2019/07/09(火) 18:47:53.66ID:jbK1WB2u0
>>311
プロトタイプと同じだからOKだよね
>>302は何を言いたいのか分からんな
2019/07/09(火) 19:48:16.54ID:YXbnrG+I0
>>301
その場合は↓で良いはず
void foo(int arg1, int)
{
}
2019/07/09(火) 20:34:43.07ID:3UBru1uA0
>>311
おまえさんは「関数原型を含む」を、「関数原型についてのみ」と脳内変換しているのか?

> int func() /* definition */
これのどこに、void型で名前のない仮引数があるんだ?
2019/07/09(火) 21:57:18.11ID:Rbs4mLR80
>>296
それは lint 対策ですよ
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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