summaryrefslogtreecommitdiffhomepage
path: root/ja-jp/c-jp.html.markdown
blob: 9dbe05692959930c2e8767ff0d7f16ac64621e91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
---
language: C
filename: learnc-jp.c
lang: ja-jp
contributors:
  - ["Adam Bard", "http://adambard.com/"]
  - ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"]
  - ["Jakub Trzebiatowski", "http://cbs.stgn.pl"]
  - ["Marco Scannadinari", "https://marcoms.github.io"]
  - ["Zachary Ferguson", "https://github.io/zfergus2"]
  - ["himanshu", "https://github.com/himanshu81494"]
  - ["Joshua Li", "https://github.com/JoshuaRLi"]
  - ["Dragos B. Chirila", "https://github.com/dchirila"]
  - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"]
translators:
  - ["Kenryu Shibata", "https://github.com/kenryuS"]
---

え、C? あぁ、**未だに**モダンで高パフォーマンスを実現できるあの言語のことだな。

Cはほとんどのプログラマが最低水準言語として使われているが、その特徴は実行速度の速さだけ
ではないのだ。CはPythonなどの高水準言語とは異なり、メモリの自動管理機能がなく、
プログラマーの手で管理する必要があり、これが初学者を苦しめる要素となるが、うまく使えば、
ロボットなどで実行速度やメモリの使用率などを大幅に最適化できる。

> **コンパイラフラグについて**
>
> gccやclangなどのコンパイラではデフォルトでデバッグに有益なエラーや警告を表示しない
> 設定になっています。なので、それらのエラーを詳細に、厳しく表示させるフラグと共に
> 実行することをおすすめします。下記はそのフラグの例です:
>
> `-Wall -Wextra -Werror -O2 -std=c99 -pedantic`
>
> このようなフラグの詳細については、オンライン検索にかけるか、
> コンパイラのドキュメンテーションを読んでください。(Linuxなら`man 1 gcc`等)

```c
// 行コメントは//で始まる (C99より前のC標準では使えない)

// Cに限ったことではないが、ソースコードで日本語コメントを書くときにはファイルを
// UTF-8で保存することをおすすめします。なぜならgccなど特定のコンパイラでは
// 文字コード変換の影響で意図しないコメントアウトが引き起こされる可能性があります。

// 例:
// forループで似たコードの繰り返しを解消することが可能
// このコメントを消すと何故か動かない
for (int i = 0; i < 100; i++) {
    printf("%d\n", i);
}
// 解説:shift-jisで「能」は 94 5c で、標準ASCIIでは 5c は"\"でLinux gccでは
// 次の行もコメントアウトされる仕様で、この例ではforループの最初の定義が
// コメントアウトされエラーとなります。

/*
複数行コメント、C89標準でも使える。
*/

/*
複数行コメントはネストできないので/*注意*/ // コメントはここで終わり、
*/ // ここのコメント終了は扱われない。

// 定数・マクロ:#define <定数名(英数字のみ)>
// 定数はすべて大文字で定義することをおすすめします。
#define DAYS_IN_YEAR 365

// 列挙体も定数を定義する方法の一つです。
// すべてのコード行は半角英数字で書き、セミコロン「;」で終わる必要があります。
enum days {SUN, MON, TUE, WED, THU, FRI, SAT};
// SUNは0、MONは1、TUEは2、などと続く。

// 列挙体の値は別の値にできますが、数字が大きくなるようにする必要があります。
enum days {SUN = 1, MON, TUE, WED = 99, THU, FRI, SAT};
// MONは自動的に2、TUEは3、と続き、WEDで99、THUは100、FRIは101、などと続く。

// #include でヘッダーファイルをインポートできる。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// <アングルブラケット>で囲まれたファイル名はヘッダーファイルをシステムライブラリから
// 探すことをコンパイラに伝え、自分で書いたヘッダーファイルを使うときには ”引用符” で
//そのファイルのパスを囲みます。
#include "my_header.h"               // ローカルファイル
#include "../my_lib/my_lib_header.h" // 相対パス

// 予め関数を .h (ヘッダー)ファイルで宣言するか、
// .c (ソースコード)ファイルの上方に書いて宣言してください。
void function_1();
int function_2(void);

// 関数を使用する前に、最低でも、関数プロトタイプを宣言しなければなりません。
// プロトタイプは関数定義の前に書くのが一般的です。
int add_two_ints(int x1, int x2); // 関数プロトタイプ
// 上記の書き方でも問題ありませんが(引数の連番)、引数にはコード保守を
// 容易にするためになるべくちゃんとした名前をつけてあげましょう。

// 関数プロトタイプはその関数を使う前に定義を書いておけば必要ありません。
// しかし、関数プロトタイプをヘッダーファイルに記述し、ソースコードの上方に#includeを
// 使ってインポートすれば、コンパイラにまだ定義されていない関数を呼び出すことを防ぎ、
// ヘッダーファイルにどんな関数が定義されるのかが分かるのでプログラムの保守性も上がります。

// プログラムが最初に実行する関数はエントリーポイントといい、Cではmain()関数となります。
// 返り値はどんな型でも良いですが、Windowsなどの大抵のOSはエラーコードを検知・処理するために
// 関数はint型(整数型)を返すことが定められています。
int main(void) {
  // プログラムはここへ
}

// コマンドライン引数はプログラムの挙動やオプションを実行時に設定することができます。
// argcは引数の数を表し、プログラム名もカウントされるので常に1以上の値が入ります。
// argvは引数文字列の配列を表し、プログラム名含むすべての引数が入るます。
// argv[0]はプログラム名を、argv[1]は最初の引数などです。
int main (int argc, char** argv)
{
  // コンソールに文字などを表示するときにはprintf関数を使います。
  // printfは”print format”のことで、書式に沿って値を表示させます。
  // %dには整数が入り、\nは新しい行("n"ew line)へ移動します。
  printf("%d\n", 0); // => 0が表示される

  // scanf関数はコンソールからユーザの入力を受け付けます。
  // 変数の前の'&'記号はメモリ上の変数の住所(address)を求める一種の演算子です。
  // この例では整数型の値をinput変数の住所に値を代入します。
  int input;
  scanf("%d", &input);

  ///////////////////////////////////////
  // 型
  ///////////////////////////////////////

  // C99標準の互換性がないコンパイラでは、そのスコープで使用するすべての変数は
  // スコープの一番上に宣言する必要があります。C99標準互換のコンパイラは、使用する前なら
  // スコープ内のどこでも宣言可能です。このチュートリアルでは、C99標準に統一して書いていきます。

  // int型は大抵の場合整数を4バイトのメモリで格納しますが、古いCPUでは2バイトで格納します。
  // sizeof演算子を使えば、その型が何バイト使うか確認できます。
  int x_int = 0;

  // short型は2バイトで整数を格納。
  short x_short = 0;

  // char型は大抵のプロセッサーでは、最小のサイズで、
  // 1バイトのサイズで整数またはASCII文字一つを格納できます。
  // この型のサイズはプロセッサーによって異なり、2バイト以上の物もあります。
  // (例:TIからリリースされたTMS320は2バイトで格納される。)
  char x_char = 0;
  char y_char = 'y'; // ASCII文字リテラルは''で囲まれる。

  // long型は4~8バイトで整数を格納します。long long型は常に8バイトであることが保証されます。
  long x_long = 0;
  long long x_long_long = 0;

  // float型は32ビットの単精度浮遊少数を格納します。
  float x_float = 0.0f; // 'f'はその数字リテラルが単精度浮遊少数であることを示します。

  // double型は64ビットの倍精度浮遊少数を格納します。
  double x_double = 0.0; // 実数のあとに何もつかない数字リテラルは倍精度浮遊少数として扱います。

  // 整数型はunsignedをつけることで0以上の正の数のみを格納させることができます。
  unsigned short ux_short;
  unsigned int ux_int;
  unsigned long long ux_long_long;

  // char型に格納されている文字はASCIIなどの文字コードに対応する整数でもあります。
  '0'; // => ASCIIで48を表す。
  'A'; // => ASCIIで65を表す。

  // sizeof(T)でその型のサイズをバイトで返す(Tには型名が入る。)
  // sizeof(obj)はその値の型のサイズを返す。(objには定数、変数、生の値が入る。)
  printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words)

  // もしsizeof演算子の引数が式だった場合、VLA(可変長配列、Variable Length Array)でない限り、
  // その式は評価されません。この場合の引数の値はコンパイル時定数である。
  int a = 1;
  // size_t型は変数などの型サイズを表す2バイト以上の非負の整数を格納します。
  size_t size = sizeof(a++); // a++ は評価されない。
  printf("sizeof(a++) = %zu where a = %d\n", size, a);
  // prints "sizeof(a++) = 4 where a = 1" (32ビット環境での場合)

  // 配列は定義時にサイズを決める必要があります。
  char my_char_array[20]; // この配列は 1 * 20 = 20 バイト使います
  int my_int_array[20]; // この配列は 4 * 20 = 80 バイト使います
  // (4バイト整数環境であると仮定した場合)

  // 次の定義では整数配列を20個の0で埋めた状態で初期値が与えられます。
  int my_array[20] = {0};
  // "{0}"は配列初期化子です。
  // 初期化子に含まれる要素以外の要素は、(もしあれば)すべて0に初期化されます:
  int my_array[5] = {1, 2};
  // 上記の定義ではmy_arrayは5つの要素があり、最初の2つ以外は0に初期化されています:
  // [1, 2, 0, 0, 0]
  // 配列定義のときに明示的に初期化を行えば、要素数を決める必要がなくなります:
  int my_array[] = {0};
  // サイズを指定しないで定義すると配列初期化子の要素数がそのまま自動的に決めまれます。
  // よって"{0}"で初期化した場合、配列のサイズは1となり、"[0]"が代入されます。
  // 実行時に配列の要素数を調べるには、配列のサイズを1つの要素のサイズで割れば良いのです。
  size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]);
  // 注意;この操作は配列ごとに、かつ関数に渡す前に実行することを勧めします。なぜなら
  // 関数に配列を渡すと、ポインター(メモリ上の場所を表す単なる整数)に変換され、
  // 関数内で同じ操作を行うと、間違った結果につながる恐れがあるからです。

  // 要素へアクセスするときは他の言語と同じようにできます。
  // 正しく言えば、Cに似た言語です。
  my_array[0]; // => 0

  // 配列は変更可能です。
  my_array[1] = 2;
  printf("%d\n", my_array[1]); // => 2

  // C99標準以降(C11では任意選択)では、可変長配列(VLA)が使用可能で、コンパイル時に
  // 定数による要素数指定をしなくても、変数などによる指定ができるようになります。
  printf("Enter the array size: "); // ユーザーに要素数を入力してもらう。
  int array_size;
  fscanf(stdin, "%d", &array_size);
  int var_length_array[array_size]; // VLAを宣言する。
  printf("sizeof array = %zu\n", sizeof var_length_array);

  // 例:
  // > Enter the array size: 10
  // > sizeof array = 40

  // 文字列はヌル文字(0x00, '\0')で終わる配列でもあります。
  // 文字列リテラルを使用する場合はコンパイラが末尾に塗る文字を追加するので明示的に
  // 入れなくても良いです。
  char a_string[20] = "This is a string";
  printf("%s\n", a_string); // %s フォーマットで文字列を表示

  printf("%d\n", a_string[16]); // => 0
  // 例, 17番目のバイトは0 (18, 19, 20番目も同様)

  // シングルクォーテーションで囲まれた文字は文字リテラルです。これはchar型*ではなく*、
  // int型です。(これには歴史的背景があります。)
  int cha = 'a'; // OK
  char chb = 'a'; // これもOK (intからcharへの暗黙的型変換)

  // 多次元配列:
  int multi_array[2][5] = {
    {1, 2, 3, 4, 5},
    {6, 7, 8, 9, 0}
  };
  // 要素の取得:
  int array_int = multi_array[0][2]; // => 3

  ///////////////////////////////////////
  // 演算子
  ///////////////////////////////////////

  // 複数の同一型変数の略記法:
  int i1 = 1, i2 = 2;
  float f1 = 1.0, f2 = 2.0;

  int b, c;
  b = c = 0;

  // 四則演算は直感的にかけます:
  i1 + i2; // => 3
  i2 - i1; // => 1
  i2 * i1; // => 2
  i1 / i2; // => 0 (0.5だが、0に繰り下げられている)

  // 結果を少数にするにはどちらか一方の変数をfloat型へキャスティングする必要がある。
  (float)i1 / i2; // => 0.5f
  i1 / (double)i2; // => 0.5 // double型でも同様の操作ができる
  f1 / f2; // => 0.5, プラスマイナス計算機イプシロン(その型が表せる最小の少数)

  // 浮動小数点数はIEEE 754の仕様で定義されているので、コンピューターは正確な
  // 数をメモリ上で保存できない。よって意図しない数になることがある。例えば、0.1は
  // 0.099999999999、0.3は0.300000000001として保存されているかもしれません。
  (0.1 + 0.1 + 0.1) != 0.3; // => 1 (真)
  // なのでこれは上記の理由でこの真偽式は真になりません。
  1 + (1e123 - 1e123) != (1 + 1e123) - 1e123; // => 1 (真)
  // こちらは科学的表記法です : 1e123 = 1*10^123

  // ほとんどのシステムはIEEE 754に基づいて浮動小数点数を定義していることを
  // 知っておくことが重要になってきます。科学演算で多用されるPythonでも最終的に
  // IEEE 754を使うCを呼び出すことになります。この注意書きはCの浮動小数点数の
  // 仕様が悪く使うべきではないということをほのめかすのではなく、こういった誤差
  // (イプシロン)を考慮した上で比較するというのを頭に入れておくために書かれました。

  // 剰余演算もありますが、負の値を計算するときには注意してください:
  11 % 3;    // => 2 (11 = 2 + 3*x (x=3))
  (-11) % 3; // => -2 (-11 = -2 + 3*x (x=-3))
  11 % (-3); // => 直感に反し被除数と同じ符号になる、2 (11 = 2 + (-3)*x (x=-3))

  // 比較演算は親しみがあるかもしれませんが、Cには真偽型がなく、
  // 代わりに整数型が使われます。(C99以降は _Bool型がstdbool.hで
  // 提供されました。) 0は偽を表し、それ以外はすべて真として扱います。
  // 比較演算を使用する際は必ず0か1を返します。
  3 == 2; // => 0 (偽) 等しい
  3 != 2; // => 1 (真) 等しくない
  3 > 2;  // => 1       より大きい
  3 < 2;  // => 0       より小さい
  2 <= 2; // => 1       以下
  2 >= 2; // => 1       以上

  // CはPythonではないので、演算子の連鎖はできません。
  // 下記の例では問題なくコンパイルしますが、`0 < a < 2`は`(0 < a) < 2`になり、
  // `(0 < a)`の結果が真でも偽でも結局`0 < 2`または`1 < 2`となるので常に真となります。
  int between_0_and_2 = 0 < a < 2;
  // 代わりにこう書きます:
  int between_0_and_2 = 0 < a && a < 2;

  // 整数に対する論理演算子:
  !3; // => 0 (否定)
  !0; // => 1
  1 && 1; // => 1 (論理積)
  0 && 1; // => 0
  0 || 1; // => 1 (論理和)
  0 || 0; // => 0

  // 条件付き三元式 ( ? : )
  int e = 5;
  int f = 10;
  int z;
  z = (e > f) ? e : f; // => 10 "もし(e > f)が真ならばeを、偽ならばfを返す。"

  // 加算・減算演算子:
  int j = 0;
  int s = j++; // jを返してからjを1増やす (s = 0, j = 1)
  s = ++j; // jを1増やしてからjを返す (s = 2, j = 2)
  // 減算演算子 j-- と --j でも同様

  // ビット演算子
  // 整数などのデータは0と1の2進数で表されておりそれぞれをビットといいます。
  // これらの演算子は各ビットに論理演算を適用します。
  ~0x0F; // => 0xFFFFFFF0 (ビット単位NOT、補数、32ビット16進数整数での例)
  0x0F & 0xF0; // => 0x00 (ビット単位AND)
  0x0F | 0xF0; // => 0xFF (ビット単位OR)
  0x04 ^ 0x0F; // => 0x0B (ビット単位XOR)
  0x01 << 1; // => 0x02 (算術左シフト (1ビット幅))
  0x02 >> 1; // => 0x01 (算術右シフト (1ビット幅))

  // 正負のついた整数に対するビットシフトには注意してください - これらの操作は未定義です:
  // - 符号ビットへのビットシフト (int a = 1 << 31)
  // - 負の整数を左シフトする (int a = -1 << 2)
  // - 型のビットサイズ以上の幅でシフト:
  //   int a = 1 << 32; // 32ビット幅の整数の場合では未定義の動作

  ///////////////////////////////////////
  // 制御構造
  ///////////////////////////////////////

  // 条件文
  if (0) {
    printf("I am never run\n");
  } else if (0) {
    printf("I am also never run\n");
  } else {
    printf("I print\n");
  }

  // whileループ文
  int ii = 0;
  while (ii < 10) { // 10以下の整数がこの条件を満たす
    printf("%d, ", ii++); // ii++ が値を使用してから1加算される。
  } // => "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "が出力される

  printf("\n");

  // do-whileループ文
  int kk = 0;
  do {
    printf("%d, ", kk);
  } while (++kk < 10); // ++kk が値を使用する*前*に1加算される.
  // => "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "が出力される

  printf("\n");

  // forループ文
  int jj;
  for (jj=0; jj < 10; jj++) {
    printf("%d, ", jj);
  } // => "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "が出力される

  printf("\n");

  // *****注*****:
  // ループ文、関数には最低でも一つの命令・文が必要になります:
  int i;
  for (i = 0; i <= 5; i++) {
    ; // セミコロン単体で何もしないという命令を作れる(ヌル命令)
  }
  // 別の表記法:
  for (i = 0; i <= 5; i++);

  // switch文(if文より高速)
  switch (a) {
  case 0: // caseレーベルにはint型や列挙型やchar型等の整数で表せるものに限定されます。
    printf("Hey, 'a' equals 0!\n");
    break; // ブレイク文がなければ後続のcaseレーベルも実行されてしまいます。
  case 1:
    printf("Huh, 'a' equals 1!\n");
    break;
    // break文がそのcaseレーベルになければ、break文があるレーベルまですべて実行されます。
  case 3:
  case 4:
    printf("Look at that.. 'a' is either 3, or 4\n");
    break;
  default:
    // 上記の条件がすべて合致しなければdefaultレーベル下の命令が実行されます。
    fputs("Error!\n", stderr);
    exit(-1);
    break;
  }

  // goto文
  typedef enum { false, true } bool;
  // C99より前のC標準ではブール値が標準で定義されていません。
  bool disaster = false;
  int i, j;
  for(i=0; i<100; ++i)
  for(j=0; j<100; ++j)
  {
    if((i + j) >= 150)
        disaster = true;
    if(disaster)
        goto error;  // 両方のforループから抜ける
  }
  error: // goto error;"で"error"レーベルまで「ジャンプ」します。
  printf("Error occurred at i = %d & j = %d.\n", i, j);
  /*
    この例の出所: https://ideone.com/GuPhd6
    "Error occurred at i = 51 & j = 99."が出力されます。
  */
  /*
    ほとんどの場合、goto文を使うのは、そのコードが何をするかわかっていない限り、
    良くないとされています。詳細は
    https://ja.wikipedia.org/wiki/スパゲッティプログラム#goto文の濫用
    を読んでください。
  */

  ///////////////////////////////////////
  // 型キャスティング(型変換)
  ///////////////////////////////////////

  // すべての値には型がありますが、これらは、互換性がある別の型にキャスティングすることができます。

  int x_hex = 0x01; // 16進数リテラルで変数を定義できます。
                    // 2進数リテラルにはコンパイラごとに差があります。
                    // (GCCではx_bin = 0b0010010110)

  // 型キャスティングを行うとその値を保持しようとします。
  printf("%d\n", x_hex); // => 1
  printf("%d\n", (short) x_hex); // => 1
  printf("%d\n", (char) x_hex); // => 1

  // キャスティング先の型のサイズより大きい値をキャストすると警告なしに値が丸められます。
  printf("%d\n", (unsigned char) 257); // => 1 (8ビット長のunsigned char型が保持できる最大値は255)

  // char, signed char, unsigned char型の最大値はそれぞれ、<limits.h>で提供される
  // CHAR_MAX, SCHAR_MAX, UCHAR_MAXマクロを使用できます。

  // 整数型と浮動小数点数型は双方向にキャスティング可能です。
  printf("%f\n", (double) 100); // %f はdouble型と
  printf("%f\n", (float)  100); // float型をフォーマットします。
  printf("%d\n", (char)100.0);

  ///////////////////////////////////////
  // ポインター
  ///////////////////////////////////////

  // ポインターはメモリ上のアドレスを保持する整数の変数であり、型と共に宣言・定義されます。
  // 変数から直接アドレスを取得できることができます。

  int x = 0;
  printf("%p\n", (void *)&x); // &を用いて変数のアドレスを取得します。
  // (%p は void *型の値をフォーマットします。)
  // => 結果: 変数が保持されているメモリーアドレスが表示される

  // ポインターは型名の直後にまたは変数名の直前に * を書いて宣言・定義します。
  int *px, not_a_pointer; // px はint型の値を指すポインター
  px = &x; // pxにxのアドレスを代入する。
  printf("%p\n", (void *)px); // => &xと同様の結果が出力されるはずです。
  printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer));
  // => 64ビット環境では"8, 4"が出力されます。

  // ポインターから指示しているメモリー領域の値を取得(ディレファレンス)するには
  // ポインター宣言と同じようにポインター名の前に * を書きます。
  printf("%d\n", *px); // => xの値である0を出力

  // この機能を用いて、ポインターが指示している値を変更することができます。
  // 加算演算子はディレファレンス演算子より優先順位が高いので数学同様ディレファレンス操作を
  // 丸括弧で括ります。
  (*px)++; // pxが指しているxの値を1加算する
  printf("%d\n", *px); // => 1
  printf("%d\n", x); // => 1

  // 配列は連続したメモリー領域を確保するのに有効です。
  int x_array[20]; // 長さ20の不可変長配列を宣言
  int xx;
  for (xx = 0; xx < 20; xx++) {
    x_array[xx] = 20 - xx;
  } // x_arrayの値を 20, 19, 18,... 2, 1 と一括初期化する。

  // int型の値を指し示すポインターを宣言し、x_arrayのアドレスで初期化する
  int* x_ptr = x_array;
  // x_ptrは整数20個の配列の最初の要素を指しています。
  // この場合配列は代入時に最初の要素へのポインターへ変換されます。
  // 関数に配列を渡す際にも暗黙的にポインターに変換されます。
  // 例外:`&`を配列に適用した場合、その配列のアドレスが返り、要素の型ではなく、
  // 配列型のポインターが使用されます:
  int arr[10];
  int (*ptr_to_arr)[10] = &arr; // &arr は `int *`型ではない!
  // これは「(10個の整数の)配列へのポインター」型です。
  // もう一つの例外には文字列リテラルをchar型配列に代入する場合:
  char otherarr[] = "foobarbazquirk";
  // または、`sizeof`, `alignof`演算子を使用した場合:
  int arraythethird[10];
  int *ptr = arraythethird; // equivalent with int *ptr = &arr[0];
  printf("%zu, %zu\n", sizeof(arraythethird), sizeof(ptr));
  // "40, 4" または "40, 8" が出力されます。

  // ポインター型の値を加算・減算するとその方に応じて操作できます。
  // この操作のことをポインター演算といいます。
  printf("%d\n", *(x_ptr + 1)); // => 19
  printf("%d\n", x_array[1]); // => 19

  // 標準ライブラリ関数の一つであるmallocを使えば連続したメモリ領域を動的に確保できます。
  // malloc関数は確保するバイト数を設定するsize_t型の引数が一つあります。
  // (確保するのは大抵の場合ヒープ領域に確保されますが、組み込みデバイスなどでは
  // 挙動が異なる場合があります。このことはC標準では説明されていません。)
  int *my_ptr = malloc(sizeof(*my_ptr) * 20);
  for (xx = 0; xx < 20; xx++) {
    *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx
  } // メモリー領域を整数型配列として初期化する [20, 19, 18 ... 1]

  // mallocで確保されたメモリー領域へのデータの書き込みには注意してください。
  // 安全性を保証するには、確保すると同時にそのメモリー領域をすべて0で埋め尽くすcalloc関数を使用してください。
  int* my_other_ptr = calloc(20, sizeof(int));

  // Cには動的配列のサイズをその場で求める方法はほとんどなく、関数などに渡すときに要素数を記録する別の変数が
  // 必要になることがよくあります。詳細は次の関数についてのセクションを読んでください。
  size_t size = 10;
  int *my_arr = calloc(size, sizeof(int));
  // 要素を追加する
  size++;
  my_arr = realloc(my_arr, sizeof(int) * size); // realloc関数で配列のサイズを更新する。
  if (my_arr == NULL) {
    // mallocやreallocなどを使う際には領域確保に異常がない確認するために
    // ヌルチェックをすることをおすすめします。
    return
  }
  my_arr[10] = 5;

  // 確保されていないメモリー領域へアクセスは予測不可能な結果を招く可能性があります。
  printf("%d\n", *(my_ptr + 21)); // => who-knows-what? が出力される**かも**、クラッシュするかもしれない。

  // メモリー領域の使用を終えたら必ずfree関数を使ってその領域を解放しなければなりません。
  // 解放しなければ、プログラムが終了しても他のプログラムからそのメモリー領域を再利用できず、
  // システム全体で使用できる容量が減ってしまいます。このことをメモリーリークと呼びます。
  free(my_ptr); // my_ptrでポイントされてるメモリー領域を解放する。

  // 文字列はchar型の配列で表せますが、よく使用されるのは文字列の最初の文字を指すcharポインターです。
  // もし、単に文字列リテラルを使用するだけならば"const char*"を使い、変更不能にしておくことが推奨されています。
  // なぜならば、本来文字列リテラルのデータは変更すべきではないからです。
  // なので、" foo[0] = 'a' "といった操作はできません。
  const char *my_str = "This is my very own string literal";
  printf("%c\n", *my_str); // => 'T'

  // char型の配列で定義されている場合は別で、文字列リテラルで初期化できますが、
  // 各要素は変更可能です。例に:
  char foo[] = "foo";
  foo[0] = 'a'; // この操作は許されており、"aoo" に変更される。

  function_1();
} // main 関数の終わり

///////////////////////////////////////
// 関数
///////////////////////////////////////

// 関数定義の構文:
// <戻り値の型> <関数名>(<引数>)

int add_two_ints(int x1, int x2)
{
  return x1 + x2; // returnで値を返す。
}

/*
関数は値によって呼び出されます。関数が呼ばれると、引数として渡した値はコピーされ、
関数内で値を変更したとしても、渡した引数の値は変わりません。(配列はこれに従わない。)

関数内で引数の値を変更したい場合はポインターとして渡す必要があり、配列も渡すときに自動的にポインターになります。

例:即興文字列反転
*/

// void型関数は値を返さない
void str_reverse(char *str_in)
{
  char tmp;
  size_t ii = 0;
  size_t len = strlen(str_in); // `strlen()` はC標準ライブラリ関数です。
                               // NOTE: `strlen` で返される文字列の長さは終端文字の
                               //       ヌルバイト('\0')を含んでいない状態です。
  // C99標準以降では、ループ定義の中にループ制御変数が定義できます。
  // 例:`for (size_t ii = 0; ...`
  for (ii = 0; ii < len / 2; ii++) {
    tmp = str_in[ii];
    str_in[ii] = str_in[len - ii - 1]; // 後ろから ii 番目の要素 を 前から ii 番目の要素にする
    str_in[len - ii - 1] = tmp;
  }
}
//NOTE: string.h のヘッダーファイルを#includeしないとstrlen()関数が使用できません。

/*
char c[] = "This is a test.";
str_reverse(c);
printf("%s\n", c); // => ".tset a si sihT"
*/
/*
一つの変数を変更することができるように、
ポインター渡しで複数の変数を変更できます。
*/
void swapTwoNumbers(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
/*
int first = 10;
int second = 20;
printf("first: %d\nsecond: %d\n", first, second);
swapTwoNumbers(&first, &second);
printf("first: %d\nsecond: %d\n", first, second);
// 変数の値が交換される
*/

// 一度に複数の値を返す
// Cではreturn文を使って複数の値を返すことができません。一度に複数の値を返すには、
// 引数にそれぞれの戻り値を格納する変数へのポインターを設定しなければなりません。
int return_multiple( int *array_of_3, int *ret1, int *ret2, int *ret3)
{
    if(array_of_3 == NULL)
        return 0; //エラーコードを返す (偽)

    //値を変更するためにポインターをディレファレンスする。
   *ret1 = array_of_3[0];
   *ret2 = array_of_3[1];
   *ret3 = array_of_3[2];

   return 1; //エラーコードを返す (真)
}

/*
引数に配列型を使用するときは、配列は必ずポインターに変換されることに注意してください。これは
malloc関数で動的に確保したものでも、静的に定義した配列でも同じことが起きます。繰り返しになるが、
Cでは引数として渡された動的配列の長さを標準仕様で知ることができません。
*/
// 引数として配列のサイズを渡してください。
// でなければ、渡された配列の長さを知る術がありません。
void printIntArray(int *arr, size_t size) {
    int i;
    for (i = 0; i < size; i++) {
        printf("arr[%d] is: %d\n", i, arr[i]);
    }
}
/*
int my_arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int size = 10;
printIntArray(my_arr, size);
// "arr[0] is: 1" などが出力される。
*/

// 関数外で定義されている変数へアクセスするにはexternキーワードを使用します。
int i = 0;
void testFunc() {
  extern int i; //この変数iは外部変数iとして使用できる
}

// 外部変数を他のソースファイルから見えないようにする:
static int j = 0; // testFunc2()を使用する他のファイルは変数jに直接アクセスできない。
void testFunc2() {
  extern int j;
}

// staticキーワードはコンパイルユニット外での変数のアクセスを禁じ、プライベートにします。
// (大抵のシステムでのコンパイルユニットとは .c ソースコードのことを指す。)
// このstaticキーワードは(コンパイルユニットの)グローバルスコープと関数スコープどちらでも使用できますが、
// 関数スコープで使用すると挙動が変わり、アクセス制限をするのではなく、変数の寿命がプログラム終了まで延長されます。
// これはその変数が関数の実行が終了したあともメモリーにとどまり、グローバル変数と同じように
// 値を保持し続けることができるようになります。グローバル変数とは違って、変数は定義された関数のスコープ内のみで使用できます。
// 更に、staticで宣言された変数は初期値が与えられてなくても必ず0で初期化されます。
// **関数をstatic宣言することで変数と同じようにプライベートにすることができます。**

///////////////////////////////////////
// ユーザー定義の型と構造体
///////////////////////////////////////

// typedefキーワードを使えば型の別名をつけることができます
typedef int my_type; // my_type は int型の別名になった。
my_type my_type_var = 0; // int my_type_var = 0; と等しい

// 構造体は複数のデータを一つにまとめたものであり、上から下の順で定義されたメンバーがメモリーに割り当てられる:
struct rectangle {
  int width;
  int height;
};

// この構造体のサイズは必ずしも
// sizeof(struct rectangle) == sizeof(int) + sizeof(int)
// にならない、なぜならコンパイル時にシステムがメモリーを割り当てやすい位置にパッディングするからである。[1]

void function_1()
{
  struct rectangle my_rec = { 1, 2 }; // メンバーは定義時に初期化できる

  // "." で個別のメンバーへアクセスできる
  my_rec.width = 10;
  my_rec.height = 20;

  // 構造体へのポインターも定義できる:
  struct rectangle *my_rec_ptr = &my_rec;

  // ディレファレンスしてからメンバーの値をセットするのも良いが...
  (*my_rec_ptr).width = 30;

  // 可読性を高めるために"->"を使ってポインターから直接メンバーへアクセスすることもできる。
  my_rec_ptr->height = 10; // (*my_rec_ptr).height = 10; と同じ
}

// 毎回structを打たなくてもいいように構造体に別名をつけることができます
typedef struct rectangle rect; // rect = struct rectangle

int area(rect r)
{
  return r.width * r.height;
}

// typedefは構造体定義と同時に使えます:
typedef struct {
  int width;
  int height;
} rect; // 無名構造体にrectと名付けている。
// これで
struct rectangle r;
// を打たなくても
rect r;
// と楽に宣言・定義できる

// サイズが大きい構造体は値渡しの代わりにポインター渡しでコピー作成の時間・メモリー使用量増大を避けることができます:
int areaptr(const rect *r)
{
  return r->width * r->height;
}

///////////////////////////////////////
// 関数ポインター
///////////////////////////////////////
/*
実行時には、関数はプログラムに決められたメモリーアドレスにあります。関数ポインターは他のポインターとほとんど変わりません。
違うところは、ポインターを使って関数を呼び出せることです。これにより、関数の引数として他の関数をコールバックとしてわすことができます。
難しいところは、他の変数へのポインターとは表記法が違ってくることです。

例:str_reverse関数をポインターとして使う
*/
void str_reverse_through_pointer(char *str_in) {
  // 戻り値がvoid型fの名前がついた関数ポインターを宣言する。
  void (*f)(char *); // 引数も一緒に書きますが、指している関数と同じ戻り値と引数の型でなければなりません(引数名は入れずにただ型を列挙する)。
  f = &str_reverse; // 関数のアドレスを代入する(アドレスは実行時に決定される)。
  // f = str_reverse; これも正しくコンパイルできる - 配列同様ポインターに変換される
  (*f)(str_in); // 関数ポインターから実行する
  // f(str_in); // この表記法でも正しく実行できる
}

/*
同じ戻り値型と引数である限り、どの関数でも使えます。
可読性と単純性を実現するために、typedefが使われます。
*/

typedef void (*my_fnp_type)(char *);

// 下記で直背ポインター変数を宣言できます:
// ...
// my_fnp_type f;


/////////////////////////////////////
// printf()を用いて文字などを出力する
/////////////////////////////////////

//特殊文字:
/*
'\a'; // 警告 (ベル) 文字
'\n'; // 改行文字
'\t'; // タブ文字 (左揃えテキスト)
'\v'; // 垂直タブ文字
'\f'; // (フォームフィードの)新規ページ
'\r'; // 復帰文字
'\b'; // バックスペース文字
'\0'; // ヌル文字 - Cでは文字列終端文字として使用される。
//   hello\n\0. \0が明示的に文字列の終わりを表している。
'\\'; // バックスラッシュ
'\?'; // 疑問符
'\''; // シングルクォーテーションマーク
'\"'; // ダブルクォーテーションマーク
'\xhh'; // 文字コード(16進数) 例: '\xb' = 垂直タブ文字
'\0oo'; // 文字コード(8進数)  例: '\013' = 垂直タブ文字

// printf等で使われるフォーマティング:
"%d";    // 整数
"%3d";   // 整数最低3桁表示 (右揃え)
"%s";    // 文字列
"%f";    // 浮動小数点
"%ld";   // 長整数
"%3.2f"; // 小数点以下2桁、小数点以上最低3桁で表示される浮動小数点
"%7.4s"; // (文字列としての浮動小数点でも同じことができる)
"%c";    // 文字(単一)
"%p";    // ポインター 注:ポインターを渡すときには (void*) 型へ
         //                変換しなければならない。
"%x";    // 整数16進数表示
"%o";    // 整数8進数表示
"%%";    // "%" を挿入する
*/

///////////////////////////////////////
// 評価順序
///////////////////////////////////////

// 順位は上から下へ、一番上は優先順位が最も高い
//------------------------------------------------------//
// 演算子                                    |  優先順位  //
//------------------------------------------------------//
//  () [] -> .                              |  左から右  //
//  ! ~ ++ -- + = *(型) sizeof               |  右から左  //
//  * %                                     |  左から右  //
//  + -                                     |  左から右  //
//  << >>                                   |  左から右  //
//  < <= > >=                               |  左から右  //
//  == !=                                   |  左から右  //
//  &                                       |  左から右  //
//  ^                                       |  左から右  //
//  |                                       |  左から右  //
//  &&                                      |  左から右  //
//  ||                                      |  左から右  //
//  ? :                                     |  右から左  //
//  = += -= *= /= %= &= ^= |= <<= >>=       |  右から左  //
//  ,                                       |  左から右  //
//------------------------------------------------------//

/******************************* ヘッダーファイル **********************************

ヘッダーファイルはC言語の重要な役割で、ソースファイル間の依存関係の管理を
容易にすることや関数などの宣言を他のファイルに分けることができます。

ヘッダーファイル内は通常のC言語と変わりませんが、ファイル拡張子が ".h" になっており、
同じディレクトリー(フォルダー)に存在するなら` #include "ファイル名.h" `で
ヘッダーファイルで宣言した関数、定数などをソースファイルで使用できます。
*/

/*
セーフガードは#includeマクロを使用する際に、複数回宣言されるのを防ぎます。
特に互いを参照しあってしまう相互依存の場合に有効です。
*/
#ifndef EXAMPLE_H /* もし EXAMPLE_H が定義されていないならば、*/
#define EXAMPLE_H /* マクロ EXAMPLE_H を定義する。*/

// ヘッダーファイル内で他のヘッダーファイルを #include することができます。
#include <string.h>

/* 通常と同じように、マクロを用いて定数を定義できます。これは
ヘッダーファイルとそれを#includeしたソースファイルで使用できます。 */
#define EXAMPLE_NAME "Dennis Ritchie"

// 関数マクロも定義できます
#define ADD(a, b) ((a) + (b))

/*
引数である変数の周りに丸括弧がありますが、これはマクロの展開時に評価順序が
意図しないものにならないようにするためです。(例:関数 MUL(x, y) (x * y);
があるとします。MUL(1 + 2, 3) は(1 + 2 * 3)と展開され、間違った答えが帰ってきます。)
*/
// struct, typedefも同じように定義できます。
typedef struct Node
{
    int val;
    struct Node *next;
} Node;

// 列挙体も同じく、
enum traffic_light_state {GREEN, YELLOW, RED};

/*
関数プロトタイプもヘッダーファイルで宣言できます。ヘッダーファイルで定義を
書くのはよろしくないとされており、定義はソースファイルで記述することを
強く勧めます。
*/
Node createLinkedList(int *vals, int len);

/*
これ以外の要素はソースファイルに残します。過剰な#includeや定義は1つの
ヘッダーファイルには入れず、別の複数のヘッダーファイルかソースファイルに
分けてください。
*/

#endif // if系列マクロの終わり
```

## 関連記事、教材(一部英語)

[CS50 日本語版](https://cs50.jp/) はハーバード大学が無料で公開しているコンピューターサイエンスコースで
字幕付きの動画と一緒にC, Python, SQL, HTML, CSS, Javascriptなどの言語を使った素晴らしいコースです。
C言語を学ぶ者は第1-5週目を受けることをおすすめします。

[Learn C The Hard Way](http://learncodethehardway.org/c/) は有料だが、良い英語での教材です。

質問があるならば、[compl.lang.c Frequently Asked Questions](http://c-faq.com) を見るのが良い。

インデンテーションや空白の使い方はどこでも一定であることが望まれています。たとえそのコードが画期的で実行速度が速くとも、
可読性が確保できなければ保守性に欠けます。良いコーディングスタイルの一つには[Linuxカーネル](https://www.kernel.org/doc/Documentation/process/coding-style.rst)のものがあります。

それでも分からんことがあったら、GPTにかける前にググってこい。
Googleは友達だからな。

[1] [【C言語】構造体を作る上でのアライメントのお話。そもそもアライメントとは...](https://creepfablic.site/2019/09/16/clangu-alignment-padding/)