【42Tokyo】 課題の振り返り – Libft –

初めまして。
42Tokyoに入学してからの1つ目の課題「Libft」に挑戦しました。
もっと理解を深めたくて振り返ることにしました。
「Libft」にはBonusを含めて43個関数があり、それらを今後の課題で活用できるように自作ライブラリとしてまとめます。
42Tokyoのコーディング方法
42Tokyoコモンコアの課題をクリアするためには、レビュー(3回)と機械採点があります。機械採点で合格するためには決まったフォーマットで提出します。(42ヘッダーを付ける、スペースではなくtabで区切る、変数宣言は関数内の先頭など)
おすすめのVScode拡張機能
42 Header(必需ツール、42ヘッダーを生成してくれる)
42 ft count line(1つの関数内のコードの行数を表示)
42-norminette(フォーマットのエラーをわかりやすく赤い文字で可視化)
42 C-Format(フォーマットのルールに従ってコードを自動整形)
man コマンド
manコマンドとは、Linuxでマニュアルを表示するコマンドです。Manuel(マニュアル)の頭文字を取ってmanらしいです。このコマンドをLinuxで打つと英語の説明文が出てきます。C言語の標準ライブラリにあるisupper()などのユーティリティ関数なども対象です。man isupper
と打つと isupper() の説明文が出てきて、man ascii
と打つとC言語には欠かせないASCIIコード表がでてきます。
man コマンド名
英語のドキュメントを読めるようになることが libft の主な課題なのですが、42の学生がNotionにまとめている日本語の説明文を参考にして実装を進めてしまったのが反省点です。
参考になるサイト
Linux man-pages project(Linux の man ページが日本語版でまとめてあるサイト)
man pageの読み方(初心者向けの man の読み方が載っている)
Makefile
C言語で複数のソースコードを一度にコンパイルするためにコマンドを作ることができる便利なテキストファイルです。42の課題でよくでてきました。
libft では特にボーナス課題をする場合、再リンク(relink)に注意したいです。relinkとは、make
コマンドを一度打ってから変更を加えていない場合に、また make
コマンドを打ったときに再ビルドされてしまう事です。正しい動作は何も起こりません。よく見るとサブジェクト(課題のPDF)にも書いてありました。依存関係を make
で指定したり 、bonus
ルールに直接コマンドがあることが原因で再リンクが起こりやすくなります。
your Makefile must not perform unnecessary relinking.(Makefileは不要な再リンクを実行しないでください)
subject.pdf
make コマンドを打つとオブジェクトファイル達がビルドされますが、実行せずに動作確認ができるオプションがあるみたいです。動作チェックに便利です。
make -n
size_t
配列の添字(index, i)、長さ(len)、メモリサイズ(count)などには size_t
を使うと安全なコードを書けるということがわかりました。以下のヘッダーを宣言することで size_t
を使うことができます。
#include <stdlib.h>
size_t は、符号なしの整数型で、常に0以上の値を持ちます。マイナスが扱えない分正の数をよりたくさん使えます。マイナスの値が渡ってくる時に使うとエラーになるので要注意です。unsigned int の別名ですが、メモリのサイズや配列の要素数などを表すためには unsigned int ではダメで size_t を使うと良いみたいです。
ssize_t という似た型がありますが、エラー処理などで -1 を使いたい時に便利な符号付き整数型です。
unsigned char
char の符号なし整数型です。環境によっては1バイト単位で 「-128 ~ 127」までしか使えない char と比べてunsigned char は「0 〜 225」まで扱うことができ、バイナリ処理をしたい時に使います。バイナリ処理とは、メモリの内容自体を直接操作することです。memcpy()
、memset()
などメモリを正確に扱う必要がある関数で使いました。
(unsigned char *)dest;
参考になるサイト
壊し屋対策
引数に来るデータを信用してはいけない事を学びました。42のレビューでは優秀な先輩方がせっかく組んだプログラムを壊しにきます。Piscine でも Rush という課題で本科の先輩にオーバーフローとメモリリークで壊されました。私のよくある壊されパターンは、
- INT_MAX 以上や INT_MIN未満 の値
- NULL や Empty の値
- 想定しない範囲外のケース
- 未定義動作
- 使わない or 使い終わったメモリの解放し忘れ
です。これらを指摘されたり対策を行うことで安全なコードを書けるエンジニアに一歩近づけます。
特にメモリリークは厳重にしないといけません。一番壊されやすいからです。チェックはこちらのコマンドでできます。
valgrind ./a.out
mallocとfree
malloc()は、動的メモリ確保を行う関数で、確保したメモリ領域へのポインタを返します。確保したメモリの解放にはfree関数を使用します。以下のヘッダーを宣言することで malloc と free を使うことができます。
#include <stdlib.h>
使い方は簡単で、コピー先を指す変数であるdestの範囲を strlen などで計算して、malloc(サイズ)に格納するだけです。文字列を扱う場合は、NULL終端分を長さ +1 して格納します。NULL終端の分がないと無限ループしてクラッシュしてしまいます。メモリが確保できなかった場合のNULL処理もセットで覚えました。main 関数など処理が終わった後に free() で解放することを忘れないようにしたいです。
dest = (char *)malloc(sizeof(char) * strlen(s1) + 1);
if (!dest)
return (NULL);
リスト構造(単方向リスト)
そろそろC言語らしいデータ構造になってきました。リスト構造は理解するまで時間がかかる分野です。ヘッダーファイルにこのように構造体を定義しました。
typedef struct s_list
{
void *content;
struct s_list *next;
} t_list;
content はリストが持つ値そのもので、next は次の要素のポインタ(進む)を指します。next だけで処理ができ、一方向にたどって処理するリストを「単方向リスト」と呼びます。また、これからの課題で出てくるであろう「双方向リスト」では、前の要素を指すポインタの prev (戻る)を扱うのでもっと複雑になりそうです。リスト構造の仕組みは、ポインタを移動させてリストのアドレスを入れ替えています。
Libft を終えた感想
Libft は、Piscineの課題の総復習に感じました。libft の読み方は「リブフト」みたいです。(最近までリブエフティーと呼んでました)私は、ファイル構成を間違えたり最終的に日本語のまとめサイトを見るなど課題の意図を読み解くのが苦手な傾向がありました。英語できるようになりたいし、頑張って本家のPDFを読む努力をしたいです。課題を終えて、C言語の分厚い入門書を一冊読んだかのような達成感がありました。レビューでは、もっと安全な書き方や冗長なコードの発見ができました。すごく丁寧にレビューをしてくれる方がたまにいるのですが話すだけで超勉強になります。
最後まで読んでいただきありがとうございました!