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
480
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
1
14
低レイヤソフトウェア技術者が YouTuberとして食っていこうとした話
sat
PRO
7
6k
ポーリングと割り込み
sat
PRO
1
73
Rook: Intro and Deep Dive With Ceph
sat
PRO
1
140
会社員しながら本を書いてきた知見の共有
sat
PRO
3
860
デバイスにアクセスするデバイスファイル
sat
PRO
1
57
ファイルシステムのデータを ブロックデバイスへの操作で変更
sat
PRO
1
46
デバイスドライバ
sat
PRO
0
76
マルチスレッドの実現方法 ~カーネルスレッドとユーザスレッド~
sat
PRO
2
170
Other Decks in Technology
See All in Technology
Amazon Inspector コードセキュリティで手軽に実現するシフトレフト
maimyyym
0
140
GCASアップデート(202506-202508)
techniczna
0
180
自治体職員がガバクラの AWS 閉域ネットワークを理解するのにやって良かった個人検証環境
takeda_h
0
280
Foundation Model × VisionKit で実現するローカル OCR
sansantech
PRO
1
410
【新卒研修資料】数理最適化 / Mathematical Optimization
brainpadpr
29
14k
Google Agentspaceを実際に導入した効果と今後の展望
mixi_engineers
PRO
3
780
歴代のWeb Speed Hackathonの出題から考えるデグレしないパフォーマンス改善
shuta13
5
470
JAWS AI/ML #30 AI コーディング IDE "Kiro" を触ってみよう
inariku
3
400
いま、あらためて考えてみるアカウント管理 with IaC / Account management with IaC
kohbis
2
380
ウォンテッドリーのアラート設計と Datadog 移行での知見
donkomura
0
140
Intro to Software Startups: Spring 2025
arnabdotorg
0
270
AIと描く、未来のBacklog 〜プロジェクト管理の次の10年を想像し、創造するセッション〜
hrm_o25
0
110
Featured
See All Featured
GraphQLとの向き合い方2022年版
quramy
49
14k
Balancing Empowerment & Direction
lara
2
570
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Intergalactic Javascript Robots from Outer Space
tanoku
272
27k
Into the Great Unknown - MozCon
thekraken
40
2k
Why Our Code Smells
bkeepers
PRO
338
57k
The Cult of Friendly URLs
andyhume
79
6.5k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
31
2.2k
Designing Experiences People Love
moore
142
24k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Docker and Python
trallard
45
3.5k
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言語では変数定義時に初期化しないと、どんな値が入っているかは未定義 ◦ 現代的な言語のように必ず初期化するより高速だが危なっかしい ◦ 変なデータが見えてしまってセキュリティホールになることも • あくまで「未定義」なので、環境によって結果は異なる