質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

5回答

2246閲覧

C言語で一度宣言した変数を破棄したい

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2021/05/23 05:47

C言語では一度宣言した変数(例えばint型)を後で破棄することはできないのでしょうか。(pythonで言うdel文のような感じ)

自分で調べた範囲では, できる・できないどちらの記述も見つけられませんでした。ググっても配列のmalloc, freeの話くらいしかヒットしません。(調べ方が悪いんだと思いますが...。)

どなたかよろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/05/23 10:41

「何のために」破棄したいのでしょうか?
退会済みユーザー

退会済みユーザー

2021/05/23 10:49

仕様として可能かどうかを知りたいだけです。
guest

回答5

0

Shadowing使うくらいならば処理を別の関数へ追い出してしまった方がいいです。
そもそも、「型がわからなくなる、修正するのが面倒くさい」のは関数が長すぎます。

C言語の場合、記述が冗長になりやすいので少し長いですが
1画面から2画面、行数にして40~80行程度に収めたいところです。
120行・160行を超える大作になると一週間後に読むときにツラいです。

投稿2021/05/29 23:57

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2021/05/30 00:07

まったく同意見ですが、これは回答ではなく他の回答へのコメントですよね?
asm

2021/05/30 00:36

「変数を破棄したい」に対して 「そんな事するくらいなら追い出せ」という回答が一つもないのは不自然と思い回答させていただきました。
Zuishin

2021/05/30 00:51

「ローカル変数」は関数のローカル変数を含む意味合いを込め、 > 最初から関数を分けるのが楽なので「楽しようとするな」という結論にはならないでしょう。 と、質問者さんの意図がわかった時点で書いたつもりになっていましたが、「そういう質問じゃない」と全否定されて終わりました。
guest

0

明示的に"変数を破棄する"方法はないはずです。ブロックは変数の寿命を制限することであって、任意の時点で破棄するわけではありませんし。

「"変数を破棄する"ことで何をやりたいのか」を明らかにすればよりよい(不自然でない)方法が見つかったりしそうにも思います。

「メモリが勿体ない」が理由じゃないですよね? RAM128byteのマイコンだったりするとそういうのは切実ですけれど、ブロックで切り分けたとしても新しい変数を前の変数と同じ場所に割り当てる保証はないです(そうなることもある)。

C

1int main() { 2 { 3 int a=100; 4 int* p=&a; 5 printf("%p\n",&p); 6 } 7 { 8 char* p="abc"; 9 printf("%p\n",&p); 10 } 11 return 0; 12}

では、Microsoft C(Visual Studio2019)では

Text

100A4FBD0 200A4FBCC

gcc(9.3.0)では

Text

10x7ffc67488bd0 20x7ffc67488bd0

となりました。

投稿2021/05/23 11:17

thkana

総合スコア7659

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/05/27 17:14

同じ名前の変数の型を途中から変えたい、とかでしょうか。そういう感じの状況に遭遇しました。 自分の遭遇した例ですが、例えば最初にある変数(aとします)をint型で宣言してからそれについての処理を書いているときに、「しまった、途中からaがdouble型のつもりで処理を書いちゃってた」みたいなことに気づいたとします。 そこでプログラムを修正するわけですが、「aがint型のつもりで書いていた部分の最後でaを破棄してからdouble型だと宣言し直せられれば、途中からの大部分を書き直さなくて済むから楽だな」という考えが浮かびました。 別のdouble型の変数(bとします)を用意して、途中でb = (double)a;としてそれ以降に出てくるaを全部bで書き直せばもちろんそれで済む話ですが、いちいち書き直すのが面倒だなと思ったので(エディタの置換機能とかあるだろ、というのは一旦置いておいて) もちろん、途中で型を変えたりするとコードが見にくくなるとかそういうこともあるでしょうが、今書いているコードは自分しか読まないし一回動かしたらもうゴミ箱に捨てるだけの使い捨てだからさっさと書き上げたい、という状況だったのでそれでいいだろうと思ったというが、変数を破棄したいと思った理由です。 で、そういや変数破棄の方法知らないなと思い、C言語の勉強も兼ねて調べてみても情報が見当たらないのでここで質問した次第です。(上の例は結局途中からを全部修正して済ませました。) 長々と変なことを書きましたが、①ズボラがしたかっただけ②C言語の仕様として気になった、の二点が理由になります。 ただ、上の状況を詳細に書いて質問すると「ヘタに楽しようとするな。以上」で回答が終わってしまうのでは?と不安になったので、C言語の仕様についての質問として投稿しました。具体的なコードを質問に書かなかったのはそういう理由です。 拙い説明になってしまったかもしれませんが、これが質問の背景です。 あと、上の例とは関係ないですがメモリのことも気になったりします。double arr[100][100][100];みたいな大きな配列を扱うこともあって、不要になった配列は解放できるならすれば健全かなと思うこともあるので(こういう宣言の仕方だとfree()で解放できなかったりして仕様がよくわからないので...)
thkana

2021/05/27 23:08

まぁ、とりあえずC言語では「途中で変数を破棄したり、型を変えられる機能はない」という結論はでちゃってますが。 > 途中からaがdouble型のつもりで処理を書いちゃってた への暫定対応であれば、ブロックで囲うということになるでしょうか。ただし、ブロックで囲うと「名前がたまたま同じ別人」が発生して、かつ前の変数の実体には変数名ではアクセスできなくなりますから、値の引き継ぎ処置はしなきゃいけなくなりますね。 int a=3; int b=a;//引き継ぎのため //あるいは、int*p=&a; { //ブロック内では、これまでのaにはアクセスできなくなる double a=b; //あるいは、double a=*p; a*=0.5; printf("%f",a); } } みたないことで。
Zuishin

2021/05/27 23:32

> 「ヘタに楽しようとするな。以上」で回答が終わってしまうのでは?と不安になったので 一つの関数の中で型を忘れるくらい長々と処理を書き、一つの変数を別の役割で使いまわしている時点でこの苦労が始まっています。 最初から関数を分けるのが楽なので「楽しようとするな」という結論にはならないでしょう。 言ってみれば両手に荷物を抱えた上で他の仕事ができず、三本目の手をはやすにはどうしたらいいですかと質問しているようなものです。 「荷物を置いた方が楽」と、外から見た人は思います。 関数にすれば配列の所有するメモリも当然解放されます。
退会済みユーザー

退会済みユーザー

2021/05/28 01:23

質問者の方はヒープ領域、スタック領域の違いと、ローカル変数がどのようにしてスタックメモリに確保されるかをまず調べた方が良いと思います。
退会済みユーザー

退会済みユーザー

2021/05/28 01:26

> 同じ名前の変数の型を途中から変えたい、とかでしょうか。そういう感じの状況に遭遇しました。 > 自分の遭遇した例ですが、例えば最初にある変数(aとします)をint型で宣言してから > それについての処理を書いているときに、「しまった、途中からaがdouble型のつもりで > 処理を書いちゃってた」みたいなことに気づいたとします。 普通はそういう事は有り得ないので、プログラム設計やコーディングスタイルを見直しましょうとしか言いようがないです。
退会済みユーザー

退会済みユーザー

2021/05/28 16:55

>thkanaさん 多分これが自分の求めていた方向の回答です。ありがとうございます。 「Cで変数の明示的な削除は不可で、ブロックで囲うことでそれっぽい事はできる(けど引き継ぎ処理を書いたりの手間はやっぱり必要)」で理解しました。 >Zuishinさん、radianさん 回答ありがとうございます。 失礼かもしれませんが「最初から書き分けろ、そんな状況になったのがそもそも間違い」というのは今回求めていない回答なので...。 質問の趣旨をうまく伝わるように説明できていなかったようです。 既に両手で荷物を持っていることを前提条件として、そのときに足でも使って目の前のドアを空けられるか?的な事が趣旨なので、最初から両手で荷物を持つな(時間をさかのぼって最初から〇〇を使うべき)というのはまた別の話だと思っています。荷物を下ろせというのも上で書いたように「それ以外の方法はないか?」と思ったから他の方法を調べているので(結局その場では荷物を下ろして処理したと上の例には書いておいたはずです)。 「そういう事は有り得ない」と言われましても実際に遭遇したものはしたので飲み込めないです、すみません。 実際に自分が遭遇した例を書いておきます。 上で書いた例では、変数の型は説明の簡単ためにintとdoubleとしましたが、実際にはdoubleとdouble complexでした。それと変数の数も一つでなく複数でもう少し複雑でした。 doubleとdouble complexでは四則演算等は基本的に同じ形式で計算式が書けますよね?なので、最初の入力でdouble型の数字で計算をしていて、途中で複素数が絡む計算が入ってきたのを契機に変数が実数型だと通らない処理を勘違いしたまま書いてしまった(実数に複素数を代入するとか)というのが自分が現実に遭遇した状況です。これは「有り得ない」ことでは無くないですか?(最初からそんなミスをしないような手順を時間を掛けてでも踏め、というのはもちろんとして、ミスをしたと気づいたその時点での話です。ましてや絶対にミスをしないことが確約される手法なんて存在しないでしょうし) ヒープ領域、スタック領域の違い等について調べようと思います。質問時点での理解は「ヒープはmalloc等で動的に確保する、freeで解放できるがスタック領域はfreeで解放できないらしい?」程度です。もし可能でしたら参考になるサイト等ございましたら教えていただけると幸いです。
Zuishin

2021/05/28 22:07

時間を遡らなくても今後はそういうことをしなくていい方法論の話ですが、まあ聞く耳持たず繰り返す人はたくさんいますよ。
thkana

2021/05/28 22:08

> 既に両手で荷物を持っていることを前提条件として、そのときに足でも使って目の前のドアを空けられるか?的な事が趣旨 それは多分わかっちゃいるけど、そういう不作法をするなというのがプログラマの「基本的な躾」ですから、そこに触れちゃうわけです。
fana

2021/05/29 03:05

状況(というか背景事情というか)がどうにもわからない話. ミスなり勘違いなりはあり得る事柄だけども, コードを書いてる途中で間違ってたと判明したなら,その時点で書き直すよね,っていうのが率直な感想. (intなのかdoubleなのかわからんけども,その型を選んだこと自体が間違いだったならば,素直に型を修正すれば良いだけなのでは…?) そこで起きている間違いを修正するんじゃなくて何やら変なつぎはぎを入れ込んでどうにかごまかすぜ!とかいう謎の方針を選択しようというのが理解できないというか有りえない姿勢(?)というか.
退会済みユーザー

退会済みユーザー

2021/05/29 08:08

何度か書いている通り、全体を書き直すのが面倒だったからです。それだけです。手直しの方法に①全体を書き直す②部分的な修正でごまかす(今回の場合変数の削除)の2つが浮かんで、②を実践するための方法をそもそも知らなかった(結局そもそも不可だと知れたわけですが)から気になった、が質問の背景です。 > そこで起きている間違いを修正するんじゃなくて何やら変なつぎはぎを入れ込んでどうにかごまかすぜ!とかいう謎の方針 プログラムの広範囲の修正と「変なつぎはぎ」の2つで後者のほうが明らかに少ない手間・時間で問題を解決できると思ったときにそうしたいと思うのが「謎」なら確かにそうですが... 前にも書いたように今の自分しか読まない、一回この場で動かしたら捨てるだけのコードでそう考えるのを有り得ないと言われてもそれは人に依るのではと思います。 躾としてそうするべき(そのほうが自分の実益にも繋がる)、という姿勢は理解できますし納得しています。ですが、休日に自分ひとりの自宅で着る服がアイロンがけしてない皺くちゃの状態だったり、自炊料理をお皿に盛り付けずに鍋から直接食らったりしていても別に大罪を犯してるわけでもないとも思うので(これは例えです)。もちろん正式な場(他人や自分が後に扱う可能性のあるプログラム)に皺だらけの服で向かうつもりもありません。そこだけわかって欲しいです。 これ以上この部分についてやりとりをしても後は並行線だと思うのでこれで締めたいと思います(質問への回答は既にたくさん頂けたので)。質問に回答いただけた皆様ありがとうございました。お時間取らせてすみませんでした。
thkana

2021/05/29 22:50

「Iotエンジニア特化型Q&Aサイト」で「エンジニアとはこうあるべきだ」という話に対して、「ボクはある条件下ではそうしない」と宣言することにどういう意味があるのかわかりませんが、エンジニアの躾はエンジニア以外には無効ですからまぁ好きにしてください。
actorbug

2021/05/29 23:03

書き捨てのプログラムなら、Pythonなどの動的型付け言語を使うことをお勧めします。 途中で型を切り替えるのも、同じ変数に型変換して代入するだけという手軽さです。
退会済みユーザー

退会済みユーザー

2021/05/30 03:33 編集

> プログラムの広範囲の修正と「変なつぎはぎ」の2つで後者のほうが明らかに少ない手間・時間で問題を解決できると思ったときにそうしたいと思うのが「謎」なら確かにそうですが... 色々調査しても解決せず、ここで質問して回答を求めてる時点で、少ない手間になってないんじゃないですか?質問自体もXY問題になっていると思います。普通に別の変数用意して書き直した方が早く終わったのではないですか?置換やリファクタリング機能を使えばそこまで苦労しないと思われますが。 型付けのきっちりした言語を使うならその言語のルールがあるので、それが合わないなら無理にC言語を使う必要もないのではという気がします。どうも用途的にシステム開発とは関係なさそうですし、数学や科学技術関係なら、もっと楽な記述の言語はあると思います。
guest

0

C言語の変数の記憶期間は、2通りしかありません。

  • 静的変数・外部変数…プログラムの起動から終了まで存在し続ける
  • 自動変数…ブロック内で宣言されて、そのブロックを抜けるまで存在する

この2つ以外のタイミングで解放したい場合は、「malloc, free」を使うしかありません。

投稿2021/05/23 11:03

maisumakun

総合スコア145208

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

変数名はブロックの中でのみ有効です。ブロックの途中で無効化することはできません。途中で無効化したいならば、入れ子ブロックを作り、その中で変数宣言すれば子ブロック内のみで有効となります。

投稿2021/05/23 08:20

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2021/05/23 08:26

そのような回答がすでにありますが。
HogeAnimalLover

2021/05/23 08:28

ああ。追記のリンク先までは見てませんでした。
退会済みユーザー

退会済みユーザー

2021/05/23 10:51

ありがとうございます。
guest

0

ベストアンサー

ローカル変数を使えば、ブロックが終わると消えます。
それ以外の方法で消すことはできません。

追記

参考:ブロックの外で変数が消える例

投稿2021/05/23 05:52

編集2021/05/23 06:16
Zuishin

総合スコア28662

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問