C言語なら俺に聞け 159

■ このスレッドは過去ログ倉庫に格納されています
2022/08/04(木) 23:32:27.83ID:yWVViPyIM
!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

C2x ドラフト
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2731.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言語なら俺に聞け 158
https://mevius.5ch.net/test/read.cgi/tech/1640401906/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
2022/08/16(火) 10:11:26.14ID:wezFOLPc0
・・・グローバル変数の書き戻し忘れとか?
39デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/16(火) 11:20:38.26ID:2x3mrzZQa
ポインタ便利ですね
2022/08/16(火) 11:58:39.88ID:dXh796NKd
すっごく抽象的でさっぱりわからんw
なんの割り込み?
どううまくいかない?
2022/08/16(火) 14:05:35.67ID:+o+ePBjP0
>>37
書いたプログラムのロジックは誤ってないと仮定して、
コンパイラによる最適化が割り込みに配慮しないなら思ったような動作にならないということはあり得る。

ある変数が途中で変更されることはないと確信できる状況なら
レジスタにロード済みの値を使いまわしたりするのはごく普通の動作。
場合によっては定数にまで畳み込まれることもある。
だけど、割り込みはそうしたメインの流れと関係なく問答無用でどこにでも割り込むから齟齬が生じる。

C99 までは割り込みや平行については言語仕様ではあまり取り決めず、
動作の詳細な部分は処理系まかせなものの volatile キーワードを付けた変数は最適化が抑制されるとか、
処理系の拡張で属性指定を付けれるとかいった機能を利用してどうにかしてきた。
(たぶん POSIX にはもうちょっと詳しい規定がありそうだと思うけど私はよく知らない。)

C11 以降はスレッドまわりの整備が進んだので割り込みでも活用できる部分は多いと思うんだけど、
オプショナルな仕様なので C11 の処理系として必須なわけではないんよ。

おそらくは使っている処理系・実行環境で使っているお決まりのパターンがあると思うからそういうのを探して
真似するのが手っ取り早いと思う。
2022/08/16(火) 19:21:50.20ID:7tUZ32LZd
そういやそんな問題に悩んでた奴でvolatileの存在知らない奴がいたな
…大丈夫だよね?
2022/08/17(水) 12:06:24.22ID:75soL8XVa
volatile で全ての問題が解決する訳じゃないけどな
知らないのはまずいな
44デフォルトの名無しさん (ワッチョイ 06ad-Lyl8)
垢版 |
2022/08/17(水) 15:44:25.95ID:VZh9Cr0g0
switch文がポンコツ過ぎて二分探索のif文で記述したくなります
case設定がへたくそなのでしょうか?
2022/08/17(水) 16:18:24.97ID:vNydwVZ40
C++にすらないoperator switch caseでも欲しいのかな
2022/08/17(水) 16:34:24.35ID:mlh+/a6xd
またも抽象化し過ぎの質問…
switchが上手くはまらなかったらelse if地獄でいいんだよ
2022/08/17(水) 18:48:10.50ID:ito9w61P0
>>44
具体的に何が不満なの?
2022/08/17(水) 19:06:06.04ID:cXiq2BCR0
スキルを磨く以外に、王道はありません
2022/08/17(水) 19:37:59.93ID:GqH3uV+md
具体的にどうポンコツなのかわからんけど
例えばaが1だったら処理1、2だったら処理2、3-15だったら処理3、16なら処理4
それ以外は処理default

if( a == 1 ){
  処理1
}else if( a == 2 ){
  処理2
}else if( a <= 15 ){
  処理3
}else if( a == 16 ){
  処理4
}else{
  処理default
}

こんなんで充分だよ
2022/08/17(水) 21:42:31.43ID:ZlUvKbke0
流れを綺麗にしたいなら
enumやマクロでシンボリックな定数を定義、ロジックはビット演算に埋め込め
2022/08/17(水) 22:05:39.48ID:ISeM0IbeH
>>42
volatile で保証された気分になっている方が問題、ちゃんと pthread を使えよ
2022/08/17(水) 22:10:35.67ID:ito9w61P0
割り込みは並行 (または並列) とは違うので pthread ほどの保証は過剰だと思う。
2022/08/17(水) 22:19:02.41ID:vZEBwtyc0
フォールスルーしないなら if else if else if .... って重ねてってもたいして変わらんしね
2022/08/17(水) 22:23:36.57ID:ZlUvKbke0
パーサとか書くなら抽象化のコストに見合うけど、もしそれほど複雑でないなら
caseラベルは各分枝に付き一つにしてしまい、分類は外部委託してしまうが楽
switch(var)→switch(CLASSFY(var))
case 'A': actionA;...

パターン: アクション

の並びに落とし込むのが難しいなら、多分switchを使うべき問題ではない
2022/08/17(水) 22:32:08.07ID:cXiq2BCR0
swich case は条件に応じて分岐するジャンプテーブルなのでどの条件に対しても同じ重さ
if else if は書かれた順に評価し、実行するので、起こりそうな条件を前に持ってくると効率化できる、かも
2022/08/17(水) 23:03:29.34ID:YK1jCeWgM
>>55
switchも連続比較する事が基本で、caseラベルの値の最小値と最大値が一定の範囲内だったら最適化でジャンプテーブルになるかもってだけでしょ
絶体にテーブルジャンプさせたければ、自前でやるしかない
2022/08/17(水) 23:06:32.99ID:ito9w61P0
リッチな処理系なら switch も常にただのテーブルということはない。 状況に応じて最適化は入る。
ただ、頻出する分岐がどれなのか予測してくれるほど十分に賢くは無いので
条件があり得る頻度によってチューニングが必要なら if に置き換えるしかしょうがないな。

GCC だとプロファイルを取ってその成果をもとに最適化することも出来る。
頻出する条件を __builtin_expect で指定するとその分岐を優先的に検査する (ようなコードを生成する) という便利機能もある。
手作業で微調整するのは不毛な感じがするから使えるものならコンパイラの賢い機能に頼るのもアリだと思う。
(試したことがないから細かいことは知らない。 たいした効果は無いかもしれない。)
2022/08/18(木) 04:30:48.90ID:X/mZUHYK0
まあ確かに>>49
switch(a){
case 1:
 処理1; break;
case 2:
 処理2; break;
case 3..15:
 処理3; break;
case 16:
 処理4; break;
default:
 処理default
}
みたいに書ければなぁって思わなくもない
2022/08/18(木) 11:21:05.54ID:ZfnRi5ov0
>>58
GCCの拡張だけどあるよ
Clangでも使える
https://wandbox.org/permlink/XQ2uCo7afhhQRyzH
2022/08/18(木) 11:23:58.91ID:C4YsUD/kd
たまーに、いちいちbreak文を書かなきゃいけないのがダルいなって思うことはあるな
ちょっと自分が作業中断すべきときかなって
2022/08/18(木) 11:41:19.30ID:DF4FCk1vd
>>59
コンパイル時定数なら利益なくね?
case:3 case:4...case:15に展開するRANGE(3, 15)マクロで十分
2022/08/18(木) 11:44:02.06ID:u9P7LJR3a
>>59
なるほどさすが GCC やね、標準に取り込んで欲しいわ
2022/08/18(木) 11:49:28.51ID:DF4FCk1vd
caseラベルの値を数値(範囲)として扱うという発想が無かった
もう素直に比較しろよ
2022/08/18(木) 11:52:35.74ID:p/limWqpa
Ruby厨登場
2022/08/18(木) 13:33:09.96ID:FzMciMIo0
caseは単なるラベル
2022/08/18(木) 14:47:46.14ID:4UGfKreUM
for文の中でswitch使うと、forを抜けるbreakを書けないのがクソ
気付かず使うとデバッグ困難なバグになる落とし穴
switchをifにするか、forの外にgotoで飛ばすしかない
switch文はC言語最大の設計ミス
2022/08/18(木) 15:55:41.52ID:C4YsUD/kd
gotoは悪って前提だな
gotoレス原理主義者?
2022/08/18(木) 15:58:47.22ID:X/mZUHYK0
そもそも多重ループからの脱出もできないし、ややこしい奴は素直にgoto使えってことだろ
2022/08/18(木) 20:24:47.46ID:+rK0/pUYd
switchからの脱出がbreakなのがおかしい
2022/08/18(木) 20:48:40.52ID:SQwD8GPSH
>>69
for からの脱出が break
while/do while からの脱出が break

で、あれば、

switch からの脱出も break であっても不適当とはいえないのではないですか?
71デフォルトの名無しさん (ワッチョイ 06ad-Lyl8)
垢版 |
2022/08/18(木) 23:03:17.54ID:1nHnTkCL0
行儀良くまじめなんてできやしなかった
夜の校舎窓ガラス壊してまわった
逆らい続けあがき続けた早く自由になりたかった

ひとつだけわかっていたこと
この支配からの~break♪
2022/08/18(木) 23:06:15.16ID:4f/YBTxPM
Javaのswitch式を逆輸入して欲しい
評判が良いのかどうか分からんけど
73デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/19(金) 00:43:51.91ID:Djh9jYCCa
endfor とか endwhile とか endcase とか悪夢でしかない
2022/08/19(金) 01:50:19.99ID:FEOcjYNtd
>>70
switchはループ制御文ではないのになんでwhileやforと同じなのか
2022/08/19(金) 05:12:37.71ID:2Y60evoq0
break は今いるブロック (波括弧といてもいい) から一つ外のブロックに出る
という意味を持つ
2022/08/19(金) 09:19:24.91ID:FT/EuRcZ0
>>75
そんなわけないだろ。
2022/08/19(金) 10:12:45.49ID:FEOcjYNtd
それならif文からも脱出できるはずだができない
あくまでswitchが特例でループ文扱いされてるので脱出できる
2022/08/19(金) 10:34:49.15ID:FT/EuRcZ0
switch やループ構文はブロックとは独立した構文で、
これらを使うときにブロックを作らないことも出来るし、
逆に関係ないところでブロックを作ることも出来るので
break をブロックと対応付けさせると変なことになるんだよな。

たとえば以下のコードでの break は実際には switch を抜けるだけなので printf は実行されるが、
ブロックを抜けるほうが自然だと思うか?

#include <stdio.h>

int main(void) {
{
switch(1) case 1: break;
printf("hello\n");
}
}
2022/08/19(金) 12:00:39.57ID:FEOcjYNtd
そんな極端な例でなくても…

case 1:
if( x < 4 ){
………
break;
}
………
break;

普通によく書くと思うが
このif文の中のbreakでもちゃんと一番内側のswitch文の外に飛んでいく

switch(k){

case 1:
{
int tmp_x; //この中だけで使う一時変数
………
break;
}
case 2:
………
}

こんな書き方でも(あまりよくないけど)ブロックは無視してswitch文の外に飛んでいく
80デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/19(金) 18:10:20.82ID:opjWCie4a
for の中の if の中の break で単に if から脱出されても
おまえなにしとんねん
開いた口が塞がらない状態になる罠
81デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/19(金) 18:16:48.08ID:opjWCie4a
do{
やりたいこと
}while(0);
っていう構造に変換するマクロは良く使われるが
switch(0) default: {
やりたいこと
}
なんかもアリなんだな
2022/08/20(土) 00:31:59.15ID:YrrCECg9M
>>81
switchの方は初めて見た!
知らずに見たらちょっと考えちゃうよw
2022/08/20(土) 13:41:46.51ID:DoG0cN1P0
考えるな
感じるんだ
2022/08/20(土) 13:47:51.88ID:zH67Kdp1d
俺は()で囲むな
85デフォルトの名無しさん (ワッチョイ ffad-4Erx)
垢版 |
2022/08/21(日) 07:14:13.14ID:sPdtHxRX0
エロい人「割り込みの中で関数呼ぶな
なぜ??
2022/08/21(日) 07:26:44.64ID:calK6kMNd
バカな会社で働いてるから
2022/08/21(日) 07:46:27.87ID:3JIuIXQv0
>>85
環境によるけど割り込みに専用のスタック使ってるシステムとかだとそのスタックサイズはそれほど大きくなかったりするからかもね
てかそのエロい人に聞けよ
2022/08/21(日) 08:14:56.03ID:lk6Yo6Bld
再入可能でない関数ならわかるな
89デフォルトの名無しさん (アウアウウー Sa63-dbST)
垢版 |
2022/08/21(日) 09:42:18.04ID:j3ukytx2a
stack8段しか無いcpuか
2022/08/21(日) 10:25:51.63ID:calK6kMNd
割込はなるべく速く返さないといけないので
関数呼び出しのオーバーヘッドを嫌うというのもある
2022/08/21(日) 16:28:21.98ID:lk6Yo6Bld
だとすると>>86でFAだな
92デフォルトの名無しさん (ワッチョイ ffad-4Erx)
垢版 |
2022/08/22(月) 09:18:01.26ID:rymTPk3V0
微妙なタイミング調整の_nop()マクロをオプティマイザが勝手に除去するのだがwwwwwwwwww
どうすりゃいいのよ
2022/08/22(月) 09:32:56.89ID:AaGiqQjO0
>>92
インラインアセンブラ
そもそも今時命令実行タイミングに依存する構成にするなよ...
2022/08/22(月) 10:11:25.02ID:xRj4VImad
Z80や6800でそんなことしてたけど
今時のCPUはnopでさえ速度が変動するからな
2022/08/22(月) 10:15:31.51ID:/BwQkwng0
インラインアセンブラも最適化の対象になることがある。
現代的な開発環境なら intrinsic 関数が提供されてないか?
96デフォルトの名無しさん (ワッチョイ 7f69-dbST)
垢版 |
2022/08/22(月) 11:43:22.34ID:sosiPY3F0
最適化するなよw
そういうのを消すための最適化だろw
97デフォルトの名無しさん (アウアウウー Sa63-dbST)
垢版 |
2022/08/22(月) 13:53:48.03ID:KX6mg0Ola
最適化したら >>96 が消えました
2022/08/25(木) 11:33:41.80ID:sT5+wQDE0
インライン記述じゃなく別個にアセンブラソースファイルに書いてアセンブルしろってことだな。
2022/08/25(木) 11:49:07.60ID:iqB4j8J+0
スカイネット 「環境の最適化のため、人類を消去しました」
2022/08/25(木) 13:23:55.27ID:sT5+wQDE0
環境の最適化のためにスカイネット自身の消去が最適だとなったら実行するのかね。
2022/08/25(木) 16:20:32.32ID:WIrE9pd90
組み込みでは下みたいに使った
__asm__ __volatile__()
2022/08/25(木) 20:06:49.61ID:PyYJPp//d
>>99
スカイネット「あれっ、誰に報告してんだろ…私ったら(テヘ)
2022/08/26(金) 06:44:51.10ID:DLmHAhGrd
>>100
i cannot self-terminate.て言ってたね
104デフォルトの名無しさん (アウアウエー Sa1f-HH83)
垢版 |
2022/09/04(日) 05:09:23.47ID:wx4H3U1ta
Learn C Programming with Dr. Chuck (feat. classic book by Kernighan and Ritchie)
freeCodeCamp.org
チャンネル登録者数 619万
105デフォルトの名無しさん (アウアウウー Sa8b-Ro21)
垢版 |
2022/09/04(日) 10:23:39.44ID:RQxkFcRFa
>>104
1本で9時間超えてるのかすげー
106デフォルトの名無しさん (ワッチョイ c710-bBdM)
垢版 |
2022/09/04(日) 19:10:32.17ID:Rodv+P070
C言語のサンプルコードで関数内で関数プロトタイプ宣言するコードに出くわしました。
コンパイル通らないだろうと思って、clangで下記のような関数内に関数プロトタイプ宣言する
コードをコンパイルするとエラーなく通りました。

C言語において関数内でプロトタイプ宣言をする利点というか理由というのはどういうものがあるのでしょうか。

#include<stdio.h>

void hello(void)
{
printf("%s\n","hello world");
}
int main(void)
{
void hello(void);
hello();
return 0;
}
2022/09/04(日) 21:54:56.70ID:moKhjs2Z0
>>106
私見だけど、その関数内でのみ呼び出すことを強調しているのかもしれない。

あと余計なこと。お遊びのネタ。本番で使うなキケン。
GCC拡張には関数の中で関数を定義できる機能がある。clangはこの先もおそらくサポートしない。
詳細が気になるなら gcc trampoline nested function で調べてね。
2022/09/04(日) 22:27:57.67ID:KVirSSMD0
main内の void hello(void); てプロトタイプ宣言(?)意味あんの?
109デフォルトの名無しさん (ワッチョイ c710-bBdM)
垢版 |
2022/09/05(月) 01:27:33.63ID:TNrcEOZR0
具体的に言うと、ここの
『UMLの状態遷移図をC言語のStateパターンで実装&単体テストしてみる』というタイトルのブログの

void init_last_substate(FSM *fsm);
関数のプロトタイプ宣言です。State.c内でプロトタイプ宣言すればいいのに
なぜかState.c内のState_init関数内でプロトタイプ宣言しているのはなんでかなと。
実装自体はSubState.c内で定義されているのでState.c内で使うのであれば
プロトタイプ宣言が必要であることはわかるんですが、なんで関数内でプロトタイプ
宣言しているのかなと。
2022/09/05(月) 01:31:45.75ID:QNR7HRCU0
>>106
言語仕様にもある有効な文法だけれど、それほど使われることはない。
宣言はそのスコープで有効になるから直接的な理由としては >>107 が述べている通り限られた範囲での使用を想定しているということだと思う。
範囲を限りたいのが何故かなのかというのはプログラム全体の構成によるので全体を見ないと意図を推し量ることは出来ない。

なので正確な事情はわからないけども、あえて一例として私がそういう書き方をするとしたらという前提で空想すると
 ・ あまり色々なところで呼ばれたくない関数がある
 ・ しかし呼び出し箇所は他の翻訳単位にあるので内部リンケージにすることも出来ない
というようなときにはヘッダにもファイルスコープにも宣言を書きたくないと思うことはあるかもしれない。
111デフォルトの名無しさん (ワッチョイ c710-bBdM)
垢版 |
2022/09/05(月) 01:40:28.48ID:TNrcEOZR0
>>110
確かにそのコードはstatic宣言を各所に織り交ぜており、他ファイルからは関数が
呼び出せないようにしてありました。公開する関数は最小限にという感じ。

関数内でも関数のプロトタイプ宣言できるというのも、C言語の中では単なる変数宣言
double p;
と同じ扱いみたいに考えればいいのかもしれないと思いました。
typedef で関数型定義できますが、それと同じような扱いということです。

とりあえず納得しました。ありがとうございます。
2022/09/05(月) 04:58:10.54ID:YC0Agv6v0
>>106
理由は昔のいわゆるK%R Cの名残だ

main(argc, argv)
char **argv;
{
extern printf(), exit();
auto i 0;
for ( ; i < argc; i =+ 1)
printf("%s\n", argv[i]);
exit(0);
}
2022/09/05(月) 04:59:26.44ID:YC0Agv6v0
今そんなことをする必要は皆無

関数の実体がグローバルなのに
宣言がローカルなのは合理性を欠くだけ
2022/09/05(月) 05:43:33.44ID:H4wLhjVj0
staticじゃなけりゃどこからでも呼べるからな
2022/09/05(月) 11:16:15.22ID:QNR7HRCU0
そこらへんはプログラム的な都合だけでなく読む人に対しての意思表示という場合もあるから必要性だけで解釈することは出来ないよ。
今から書くプログラムではやめといたほうが良いが、この場合は今、目の前に実際にそう書かれているものがあるという話だから……。
2022/09/05(月) 12:45:24.21ID:NIl1ZTkW0
何か古い記述方法だった気がする
117デフォルトの名無しさん (ワッチョイ 675f-aOQU)
垢版 |
2022/09/05(月) 17:10:39.70ID:BqjHubPk0
何十年も前の機種依存C言語かもな
2022/09/05(月) 21:43:16.79ID:WAs1jsMo0
古い表記を引っ張ってきたのか
意思表示としてそう記述した(可能性が高い)のか
全て俯瞰してみないとい結論は出ないだろうが
そうできたところで、自分が使うことはないだろうといった代物
119デフォルトの名無しさん (ワッチョイ 5fad-XKc1)
垢版 |
2022/09/05(月) 22:13:22.67ID:hTc6qxUq0
うむ。ないなあ。
120デフォルトの名無しさん (アウアウウー Sa8b-Ro21)
垢版 |
2022/09/06(火) 09:31:54.11ID:9WMtC8ULa
namespace ってイマドキの C にあるの?
2022/09/06(火) 10:01:27.84ID:8iFyZ+3k0
ない
2022/09/06(火) 20:11:23.99ID:OXwnsseu0
今度の規格には static_assert は入るのでしょうか?
2022/09/06(火) 20:15:43.73ID:TAdoM7Dg0
>>122
C23 に static_assert は入る。
C11 から _Static_assert が有ったけどこれも Alternative Spelling として残る。
124デフォルトの名無しさん (ワッチョイ c710-CzlZ)
垢版 |
2022/09/07(水) 01:40:32.73ID:nFqp2Ghc0
構造体の一括初期化の仕組みがよくわかりません。
#include<stdio.h>
enum Flag { First = 1, Second = 2, Third = 3, Finish = 4 };
typedef struct _FSM {
size_t eof;
size_t bytes;
size_t flags;
} FSM;
static FSM initState = { 0, 0, First};

void FSM_init(FSM *self) {
self = &initState;
}

int main(void) {
FSM fsm;
FSM_init(&fsm);
printf("%zu", fsm.flags);
return 0;
}
とFSM_initでFSM構造体のメンバの初期化を行おうとしたのですが、fsm.flagsにはゴミの値が入ってしまいます。
&self = initState;ではなく一つ一つ所属物を初期化すればちゃんと初期化できるのですが、
できればこの一括で初期化する方法のどこがまずいのか教えてほしいです。
125デフォルトの名無しさん (ワッチョイ c710-CzlZ)
垢版 |
2022/09/07(水) 01:42:03.54ID:nFqp2Ghc0
肝は
static FSM initState = { 0, 0, First};
でここの初期化がまずいみたいですがよくわかりません。
2022/09/07(水) 01:45:22.24ID:n6FjKa3l0
*self = initState;
127デフォルトの名無しさん (ワッチョイ c710-CzlZ)
垢版 |
2022/09/07(水) 02:03:29.87ID:nFqp2Ghc0
>>126
うまくいきましたが、すいません。
*self=initState;

self = &initState;
の違いがわかりません。
ポインタに対してなんでアドレスを渡す形だとまずいことが理解できません。
2022/09/07(水) 02:27:51.81ID:FvUlSDCrd
>>127
>self = &initState;
selfはアドレスをコピーした仮引数
2022/09/07(水) 03:14:26.39ID:7wpEGaL10
*selfはselfの実体の参照
&initStateはアドレスの参照
2022/09/07(水) 07:32:36.16ID:UR0dF6Y90
>>127
self = &initState;
これはポインタ変数selfにinitStateのアドレスを代入するが
このままFSM_init関数から戻っているので、代入結果が即座に破棄され
何もしていないに等しい

*self = initState;
これはポインタ変数selfが指し示す先つまり構造体変数fsmに
構造体変数initStateの内容を転記する
FSM_init関数から戻ってもmainの変数fsmは残っているので
後続のprintf関数の実行結果に反映される
2022/09/07(水) 09:54:43.70ID:S6Oj2ikO0
void func(int a) { a = 10; }

int b = 50;
func(a);

とやっても a は 10 にならず a は 50 のまま
関数引数の型のままの書き戻しは 呼び出し元に反映されない
これを int → int * に読み替えた場合が質問のケース
2022/09/07(水) 10:01:21.59ID:S6Oj2ikO0
訂正
 int b = 50;
 func(b);
 とやっても b は 10 にならず b は 50 のまま
2022/09/07(水) 10:16:34.68ID:S6Oj2ikO0
・ポインタを渡して関数内ではその指し先を利用して内容を書き換える (scanf みたいな感じ)
・戻り値で内容をどかっと戻す (=呼び出し元で代入してね)

Cの文法ではこの2パターン
2022/09/07(水) 20:35:02.84ID:DxyXj8J8H
>>127
参照 & は「ポインタで書くやりかた」の見せ方を変えただけ、と考えるのがいい
すなわち、ポインタを使った書き方に習熟しないかぎり、参照の意味はわからない
参照をポインタから切り離して理解するのは不可能

参照がわからなければ、まず、ポインタを使った書き方ばかりで書きまくり、ポインタなら自信がある、くらいになるのがいい
参照はポインタを理解してからはじめて使い始めるべきもの
135デフォルトの名無しさん (ワッチョイ c710-CzlZ)
垢版 |
2022/09/07(水) 21:11:00.47ID:nFqp2Ghc0
>>134
いやさすがにそこはわかるんで・・・。

ポインタ変数を格納している仮引数に新しいアドレス値を代入しても
関数から出たら破棄されるので意味ないってことやね。
ポインタ変数宣言してたんで勝手に実体参照されるものかと思ってた。

当初fsm構造体のメンバにstateという構造体の変数をおいてそれを初期化していたので、
fsm->state = &initState;
だとうまくいくのになんでだろうと思って聞いた。
この場合、fsm->stateで実体参照しているわけやね。
136デフォルトの名無しさん (ワッチョイ c710-CzlZ)
垢版 |
2022/09/07(水) 22:08:19.73ID:nFqp2Ghc0
FILE *fp;
errno_t err;
err = fopen_s(&fp, "file.txt", "rb");
でfopen_s関数の場合、第一引数はFILE構造体のポインタのアドレス参照したものを
渡さないといけないですが、これなんでポインタじゃまずいんですか。
2022/09/07(水) 22:22:19.78ID:gjYyI5to0
ポインタに入ってる数値を書き換えるからそうじゃなきゃ変えられないでしょ
fopenの中でメモリ確保しててそのポインタの数値を確保したアドレスに書き換えてるの
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。