初学者すぎてもはや誰も書いてくれてないレベルのことで
つまずきまくったのをまとめました
誰かの参考になるといいな。
- 引数についてる「*」と「&」は何?
- printfでintの中身を出力したい
- printfでboolを出力したい
- main関数の戻り値って必要?
- hppファイル(ヘッダーファイル)には何を書いておくと便利?
- どう見ても同じフォルダにあるヘッダーファイルを#includeでインクルードしてるのにvscode上で赤い波線が出る
- vscode上のエラー(赤い波線)はどうしたら消える?そんでどのタイミングで消える?
- ドライバとライブラリの違い
- ライブラリとドライバをコンパイルに含めたいとき、CMakeLists.txtに記述する内容の違いは?
- ライブラリ、ドライバをコンパイルに含めたいときのCMakeLists.txtの書き方
- コンパイラには種類がある
- CMakeを使うほどでもない小さいアプリだったら、CMakeLists.txtを作らずに コマンドだけでビルドしたほうが楽
- 配列のサイズをデカくしたら途端に動かなくなった。
引数についてる「*」と「&」は何?
「*」:「ポインタ型」、「参照先の値を使う」
「&」:「アドレスを取得する」
関数に配列とか構造体を渡すときにポインタを使うと「値のコピー」ではなく「元データの操作」ができる
例:
void update(int* p) {
*p = 100; // pが指す先の値を更新
}
int main() {
int x = 10;
update(&x); // xのアドレスを渡す // x は 100 になる
}
printfでintの中身を出力したい
printf() の第一引数は書式文字列(例: “%d”)が必要で、
第一引数に int を渡すと、char* として解釈してメモリを参照しようとしてクラッシュやゴミ表示になる。
正しい書き方:printf(“%d\n”, intの変数);
printfでboolを出力したい
三項演算子を使って次のように記述
printf(“%s\n”, bool型の変数 ? “true” : “false”);
main関数の戻り値って必要?
main()の戻り値はOSに終了コードを返すために存在している。
マイコン(Raspberry Pi Pico等)はOSがないから「return 0;」の意味はあんまりないけど、C言語の文法的に必要だから書いておくのが丸いっぽい。
省略するとコンパイルエラーになることもあるらしい。
※C++11以降はmain()のreturn 0;を省略しても自動的に0が返される仕様らしい。でも書いてたほうがわかりやすいし他の環境でも安全だね。
hppファイル(ヘッダーファイル)には何を書いておくと便利?
- #include類
- 関数の宣言
- 定数の宣言
- 構造定義体
を宣言しておくと、cpp,c(ソースファイル)がスッキリ書けがち
どう見ても同じフォルダにあるヘッダーファイルを#includeでインクルードしてるのにvscode上で赤い波線が出る
CMakeLists.txtに不備がある。
例えばソースファイルの「#include “pico_graphics.hpp”」に赤い波線が出てうまく読み込めてなさそうな場合は、CMakeLists.txtでtarget_link_librariesにこんな感じで記述を追加
target_link_libraries(プロジェクト名
pico_graphics
)
vscode上のエラー(赤い波線)はどうしたら消える?そんでどのタイミングで消える?
CMakeを使ってるときに限った話かもしれないけど、こんな感じ
正しくCMakeLists.txtを記述
↓
ビルドする
↓
c,c++向けのインテリセンスに各ファイルの位置が伝えられる
↓
参照エラーが消える。
ドライバとライブラリの違い
ライブラリ
アルゴリズムや便利関数など、ハードウェアに依存しない再利用可能な処理群(例:描画ライブラリ、文字列処理)
ライブラリはロジックやデータ処理などの高レイヤー。
ドライバ
ハードウェアとの低レベルなやり取りを抽象化したコード(例:LCD, SPIデバイス)
ドライバは主にGPIO操作・レジスタ設定などの低レイヤー。
ライブラリとドライバをコンパイルに含めたいとき、CMakeLists.txtに記述する内容の違いは?
どっちも同じ。
ライブラリ、ドライバのある階層のCMakeLists.txtにadd_library()で定義してれば、
そのライブラリを参照したいソースがある階層のCMakeLists.txtでadd_subdirectory()とtarget_link_libraries()を記述して呼び出していればOK
ライブラリ、ドライバをコンパイルに含めたいときのCMakeLists.txtの書き方
2パターンある。
- ライブラリ、ドライバの本体がある階層のCMakeLists.txtで「○○って名前のライブラリありますよ~」って書いて、それを使いたい階層のCMakeLists.txtで呼び出すパターン
- ライブラリ、ドライバを使いたい階層のCMakeLists.txtで「この遠くのフォルダのファイルたちを1つのライブラリとして扱う」って全部書くパターン
より汎用性のある前者だけ解説
例:
lib/pimoroni-pico-main/drivers/st7789フォルダ内のファイルたちをst7789という名前のドライバとして宣言して、プロジェクトの一番上の階層にあるmain.cppで使いたい場合
lib/pimoroni-pico-main/drivers/st7789/CMakeLists.txt
# st7789って名前のライブラリ・ドライバを作る宣言
# INTERFACE
add_library(st7789 INTERFACE)
# 必要なソースを指定
target_sources(st7789 INTERFACE
${CMAKE_CURRENT_LIST_DIR}/st7789.cpp)
# ヘッダファイルを探すフォルダを指定
target_include_directories(st7789 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# st7789ドライバを動かすために更に必要な他のライブラリたちを指定
target_link_libraries(st7789 INTERFACE pico_stdlib hardware_spi)
main.cppと同じ階層のCMakeLists.txt
add_subdirectory(lib/pimoroni-pico-main/drivers/st7789)
target_link_libraries(プロジェクト名 PRIVATE st7789)
コンパイラには種類がある
arm-none-eabi-gcc → ラズパイピコ上で動くバイナリをビルドするためのやつ
gcc.exe → windows用の.exeを作るためのやつ
g++.exe → windows用の.exeを作るためのやつ(C++の場合に使用)
CMakeを使うほどでもない小さいアプリだったら、CMakeLists.txtを作らずに コマンドだけでビルドしたほうが楽
C++ならg++.exeを指定する
フルパスがダルかったら環境変数を設定()
“C:\xxxx\xxxxx\x86_64\13.2.0-16.0.6-11.0.1-msvcrt-r1\mingw64\bin\g++.exe” main.cpp -o プロジェクト名.exe
配列のサイズをデカくしたら途端に動かなくなった。
スタックオーバーフローしている。
関数の外に出してグローバル変数にすると一応動く。