Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
C言語を知らない人がびっくりしそうなC言語の特徴 ~変数定義編~
Search
Satoru Takeuchi
PRO
January 17, 2023
Technology
1
430
C言語を知らない人がびっくりしそうなC言語の特徴 ~変数定義編~
以下動画のテキストです。
https://youtu.be/g7ZcZTkOAl4
Satoru Takeuchi
PRO
January 17, 2023
Tweet
Share
More Decks by Satoru Takeuchi
See All by Satoru Takeuchi
利きプロセススケジューラ
sat
PRO
5
2.9k
俺とVSCode Python Debugger Extension
sat
PRO
1
180
コード再利用のしくみ ライブラリ
sat
PRO
3
49
AWKへの愛を語る
sat
PRO
3
520
syncコマンドのデータ同期 完了待ちやエラー検出
sat
PRO
0
64
動作中のLinux環境の全メモリを見る
sat
PRO
1
96
Linuxの時間を10秒止める
sat
PRO
2
210
プロセスへのメモリ割り当て4 - 実際に使うときにメモリを獲得するデマンドページング(実践編)
sat
PRO
1
120
プロセスへのメモリ割り当て(3) 実際に使うときにメモリを獲得するデマンドページング
sat
PRO
1
73
Other Decks in Technology
See All in Technology
TypeScriptの次なる大進化なるか!? 条件型を返り値とする関数の型推論
uhyo
2
1.7k
Zennのパフォーマンスモニタリングでやっていること
ryosukeigarashi
0
230
テストコード品質を高めるためにMutation Testingライブラリ・Strykerを実戦導入してみた話
ysknsid25
7
2.7k
ノーコードデータ分析ツールで体験する時系列データ分析超入門
negi111111
0
430
iOS/Androidで同じUI体験をネ イティブで作成する際に気をつ けたい落とし穴
fumiyasac0921
1
110
Mastering Quickfix
daisuzu
1
120
Oracle Cloud Infrastructureデータベース・クラウド:各バージョンのサポート期間
oracle4engineer
PRO
29
13k
DynamoDB でスロットリングが発生したとき/when_throttling_occurs_in_dynamodb_short
emiki
0
270
Flutterによる 効率的なAndroid・iOS・Webアプリケーション開発の事例
recruitengineers
PRO
0
120
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
0
110
FlutterアプリにおけるSLI/SLOを用いたユーザー体験の可視化と計測基盤構築
ostk0069
0
120
データプロダクトの定義からはじめる、データコントラクト駆動なデータ基盤
chanyou0311
2
350
Featured
See All Featured
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
28
2k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
Typedesign – Prime Four
hannesfritz
40
2.4k
Fireside Chat
paigeccino
34
3k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
How STYLIGHT went responsive
nonsquared
95
5.2k
A better future with KSS
kneath
238
17k
Facilitating Awesome Meetings
lara
50
6.1k
Embracing the Ebb and Flow
colly
84
4.5k
What's new in Ruby 2.0
geeforr
343
31k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Building Adaptive Systems
keathley
38
2.3k
Transcript
C言語を知らない人がびっくりしそうな C言語の特徴 ~変数定義編~ Jan. 17th, 2023 Satoru Takeuchi twitter: satoru_takeuchi
はじめに • 想定聴衆 ◦ 「C言語は聞いたことはあるがどんなものか知らない」という人 ◦ メモリ管理を自分でしなくていいプログラミング言語を使っている人 ▪ ここ十数年で生まれた言語はだいたいそう •
はなすこと ◦ 想定聴衆に向けてC言語の特徴を紹介 ◦ 今回は変数定義について • 環境 ◦ OS: Ubuntu 20.04/x86_64 ◦ gcc: Ubuntu 9.4.0-1ubuntu1~20.04.1
変数定義時の振る舞い • ほとんどの人が思い浮かべる挙動 ◦ デフォルトの値に初期化される • C言語の挙動 ◦ 変数を定義するだけでは何が入っているかは未定義 ◦
別の関数を呼び出したときに定義した別のデータの残骸がのこっているかも
サンプルコード1 1. main()の中で変数iを定義 2. iの値を表示 • 実行結果はどうなる? ◦ 直観的には0を表示 #include
<stdio.h> int main(void) { int i; printf("%d\n", i); }
サンプルコード1の実行結果 • 0が表示された ◦ C言語としてiを0に初期化しているのではなく、「たまたまこうなった」だけ #include <stdio.h> int main(void) {
int i; printf("%d\n", i); }
サンプルコード2 1. foo()を呼ぶ 1.1. 変数iを定義して100で初期化 2. bar()を呼ぶ 2.1. 変数iを定義して初期化はしない 2.2.
iの値を表示 • 実行結果はどうなる? ◦ 現代的な言語なら0になりそう #include <stdio.h> void foo(void) { int i = 100; } void bar(void) { int i; printf("%d\n", i); } int main(void) { foo(); bar(); }
サンプルコード2の実行結果 • 初期化してないbar()内の変数iの値が100 #include <stdio.h> void foo(void) { int i
= 100; } void bar(void) { int i; printf("%d\n", i); } int main(void) { foo(); bar(); }
挙動の説明 1. 前提知識となるスタックの説明 2. サンプルコード2の挙動の説明
スタックとは • プログラムの関数呼び出しの流れとローカル変数を管理するしくみ • データ構造はスタック(であるがゆえにスタックという名前がついている • 関数を呼び出すたびにローカル変数を含むスタックフレームというものをpushする というイメージ • 一般にメモリアドレスの大きな方向から小さな方向に伸びる
スタックの説明(1/4) #include <stdio.h> void bar() { int i = 100;
} void foo() { int i = 10; bar(); } void main() { int i = 1; foo(); } メモリ スタック … … いろいろ mainのiの値(1) 0 大きい アドレス 📝 戻りアドレスとか フレームポインタとか
スタックの説明(2/4) #include <stdio.h> void bar() { int i = 100;
} void foo() { int i = 10; bar(); } void main() { int i = 1; foo(); } メモリ スタック … … いろいろ mainのiの値(1) 0 大きい アドレス fooのいろいろ fooのiの値(10) push
スタックの説明(3/4) #include <stdio.h> void bar() { int i = 100;
} void foo() { int i = 10; bar(); } void main() { int i = 1; foo(); } メモリ スタック … … いろいろ mainのiの値(1) 0 大きい アドレス fooのいろいろ fooのiの値(10) barのいろいろ barのiの値(100) push
スタックの説明(3/4) #include <stdio.h> void bar() { int i = 100;
} void foo() { int i = 10; bar(); } void main() { int i = 1; foo(); } メモリ スタック … … いろいろ mainのiの値(1) 0 大きい アドレス fooのいろいろ fooのiの値(10) ゴミ ゴミ(100) pop
スタックの説明(3/4) #include <stdio.h> void bar() { int i = 100;
} void foo() { int i = 10; bar(); } void main() { int i = 1; foo(); } メモリ スタック … … いろいろ mainのiの値(1) 0 大きい アドレス ゴミ ゴミ(10) ゴミ ゴミ(100) pop
サンプルコード2の挙動の説明 #include <stdio.h> void foo(void) { int i = 100;
} void bar(void) { int i; printf("%d\n", i); } int main(void) { foo(); bar(); } メモリ スタック … … いろいろ 0 大きい アドレス
サンプルコード2の挙動の説明 #include <stdio.h> void foo(void) { int i = 100;
} void bar(void) { int i; printf("%d\n", i); } int main(void) { foo(); bar(); } メモリ スタック … … いろいろ 0 大きい アドレス fooのいろいろ fooのiの値(100) push
サンプルコード2の挙動の説明 #include <stdio.h> void foo(void) { int i = 100;
} void bar(void) { int i; printf("%d\n", i); } int main(void) { foo(); bar(); } メモリ スタック … … いろいろ 0 大きい アドレス ゴミ ゴミ(100) pop
サンプルコード2の挙動の説明 #include <stdio.h> void foo(void) { int i = 100;
} void bar(void) { int i; printf("%d\n", i); } int main(void) { foo(); bar(); } メモリ スタック … … いろいろ 0 大きい アドレス barのいろいろ barのi(100) push 初期化していないので fooのゴミが残っている!
まとめ • C言語では変数定義時に初期化しないと、どんな値が入っているかは未定義 ◦ 現代的な言語のように必ず初期化するより高速だが危なっかしい ◦ 変なデータが見えてしまってセキュリティホールになることも • あくまで「未定義」なので、環境によって結果は異なる