宿題:命令型言語1#
Homework 約30分 答え
次のC言語プログラムを適当な実行環境で実行し,その出力結果を答えよ.さらに各出力行に対して,何番目のarrayの右辺値とアドレスを出力しているかを答えよ."%p"はアドレスを16進で表示する書式指定である.
#include <stdio.h>
int main() {
    int array[3] = {1, 2, 3};
    for (int i = 0; i < 3; i++) {
        printf("%d %p\n", array[i], &array[i]);
    }
    printf("\n");
    int *p = array;
    int offset = 1;
    printf("%d %p\n", *(p+offset), p+offset);
    *(p+offset) += 5;
    printf("%d %p\n", *(p+offset), p+offset);
    p++;
    printf("%d %p\n", *p, p);
}
以下の書式をコピーして回答せよ.左側が出力結果,//以降が値の意味である.
Answer
1 0x7ffd76b36d3c  // array[0]の右辺値とアドレス
2 0x7ffd76b36d40  // array[1]の右辺値とアドレス
3 0x7ffd76b36d44  // array[2]の右辺値とアドレス
2 0x7ffd76b36d40  // array[1]の右辺値とアドレス
7 0x7ffd76b36d40  // array[1]の右辺値とアドレス
7 0x7ffd76b36d40  // array[1]の右辺値とアドレス
*(p+offset)は配列ポインタの典型操作である.基準点となるポインタにオフセット(補正値)を加えることで,任意の配列要素にアクセスできる.
ポインタで混乱している人は以下の図をよく考えること.
Q&A#
誤字#
- <ジャンプ文> ::= goto <ラベル>";" | ...
 低姿勢停止性問題-32,767~32,768-32,768~32,767
thx
試験の過去問の答えを隠す機能が欲しい#
OK
アドレスの桁を増やしたほうが読みやすいかも#
確かに.来年考えます.
"Goto Statement Considered Harmful"はDijkstraの言ではないらしい#
編集者が直したそうです.とはいえ当該記事の著者はDijkstraです.
コンパイラがおとなしい言語は?#
Pythonはかなりおとなしいです(インタプリタ型なので当然といえば当然).実行するまでエラーに気付けないともいえる.
gotoが推奨される状況はあるか?#
 ない.新しい言語はもはやgotoを採用していない.
コンピュータ側からするとむしろgotoを使った方が親切ではないか#
 コンパイラを楽にさせても大したメリットはない.
コンピュータよりも人に親切にやろう.プログラミングのほとんどの問題は人が原因です.プログラミングにおいては人を最優先に扱って下さい.まずは可読性です.そのために抽象度の高い表現を積極的に使って下さい.
ポインタの*と正規表現の*は全く別物で単なる記号の重複か?#
 Yes
int *pかint* pか?#
  動的型付け言語と静的型付け言語で実行速度の差はあるか?#
ある.動的は型推論が必要なため遅くなります.ただ様々な工夫(JITコンパイル等)でカバーしています.
型推論の際にintとlongをどう見分けているのか?#
 まず「推論」なので不確実性を伴う処理だと認識して下さい.そのうえで互換性のある型をどう扱うかは言語によります.RustやHaskellは安全な型を選びます.この場合longの方が広いので安全です.
goto以外にも低水準で不要説が唱えられている構文はあるか?#
 良い質問 👍👍👍
今日の講義で扱う動的メモリ確保malloc() free()は低水準命令です.
また,不要とは言わなくても抽象度の高い記述ができるパターンがたくさんあります.例えばJavaによるループ処理を考えよう.文字列の配列arrの全要素を大文字化して出力する処理を考える.
まずはよくあるfor文.汎用的だが低水準だといえる.
String arr[] = {"a", "ab", "aaba"};
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i].toUpperCase());  // A AB AABA
}
拡張for文で置き換える.誘導変数iが減るだけでなく可読性も上がる.添字のバグも減る.
String arr[] = {"a", "ab", "aaba"};
for (String s: arr) {
    String tmp = s.toUpperCase();
    System.out.println(s.toUpperCase());  // A AB AABA
}
Stream APIとラムダ式を使うとベスト.命令的ではなく宣言的に書く.まさに関数型の考え.
String arr[] = {"a", "ab", "aaba"};
Stream.of(arr).map(String::toUpperCase)
              .forEach(System.out::println);  // A AB AABA
break continueの代わりにgotoを使うのはアリか?#
 ナシです.構造化プログラミングの考えには則ってますが,それでもgotoは極力避けるべきです.関数 + returnを使おう.
gotoを使いたくなるよくあるケースは二重ループの脱出です.
フラグを使えば抜けられるがダサい.
for (int i = 0; ...) {
    for (int j = 0; ...) {
        if (...) { flag = 1; break; }  // break前にflagを立てる
        ...
    }
    if (flag) break;  // う~ん
}
gotoなら解決するがダサい.
関数 + returnを使おう.
今日の授業は関数の話をします.
変数のメモリ領域はどのような規則で確保されるのか?ランダムか?#
今日の授業でやります.
各研究室の情報を知る手段は?#
B4の研究室配属の際に見学がありますが,かなり遅いとは思います.自主的に動くしかない.調べる・見学を依頼する等やってください.夏休み・冬休みはおすすめです.