おとついの晩ご飯

忘れやすいので忘れたくないことを書いています。

【C++】汎用ポインタについて

問題

汎用ポインタとは。。。


理解

あらゆる型のポインタを入れることができるポインタ。
以下のような書き方

// void型の変数を定義する
void *p_data;

int num = 10;

// int型のポインタを入れることも可能
p_data = &10


std::string str = "aaa";

// std::string型のポインタを入れることも可能
p_data = &str;


// 入れた値を取り出す時はキャストして使う
auto data = static_cast<std::string*>(p_data);
// 値を取得する
data = *data;

注意

汎用性があり便利だが、積極的に使う場面はあまり想定できない。
使用機会は少なそう。。。
確実に正しい型にキャストしないといけないので、その保障ができる場合のみ使用する。

【C++】マスクビットについて

問題

マスクビットとか知らん。


解決

たくさんのフラグ情報をひとつにまとめて使えるビットフラグで、特定のフラグが立っているかの確認ができる。
以下、使い方。

const int FLAG_A = 0x00000001; // 0bit (0000 0001)
const int FLAG_B = 0x00000002; // 1bit (0000 0010)
const int FLAG_C = 0x00000004; // 2bit (0000 0100)
const int FLAG_D = 0x00000128; // 7bit (1000 0000)

int flagAll = 0;

if(true)
{
    // 0bitが1となりフラグが立つ
    // 0000 0001
    flagAll |= FLAG_A;
}

if(true)
{
    // 1bitが1となりフラグが立つ
    // 0000 0011
    flagAll |= FLAG_B;
}

if(true)
{
    // 2bitが1となりフラグが立つ
    // 0000 0111
    flagAll |= FLAG_C;
}

if(true)
{
    // 7bitが1となりフラグが立つ
    // 1000 0111
    flagAll |= FLAG_D;
}


// ※※※※※※※※※※※※※※※※※※※
// 7bit目が立っているか確認
if((flagAll & FLAG_C) == FLAG_C)
{
    // フラグが立っているときの処理
}

という風にマスクビットを使うことで、特定のフラグ(マスクビットで表した全て)が立っているかを簡単に確認できる。


ビットというだけで苦手意識があったけど、これなら自分でも使える。

参考サイト

qiita.com

【C++】変数の初期化について

問題

値を代入していない変数が初期化されている
C#では初期化されなかったと思うけど。。。

解決

調べてみるとC++では以下のような宣言だけでもデフォルトコンストラクタで初期化される。

// 空文字の状態
std:string str;


ついでC#の方も調べてみると、メンバー変数は同じように初期化されるみたいだが、ローカル変数は初期化されないとのこと。

だから変な感じがしたのか。。。

ちなみにこれに気づいたのは静的解析で値を代入していない変数宣言に指摘を受けていたから。
初期化もしていないのになんで例外はく可能性があるんや?と思っていいたらそういうことだったのか。

【C++】Externについて 他のファイルの変数・関数を使う

問題

他のファイルで定義されている変数や関数をつかうにはどうすればよいか

解決方法

Externを使う。
使用例は以下。Moto.cppで定義されている変数と関数をSaki.cppでExternして使う。


・Moto.cpp

int MaxNum;

void TasuIch(int num)
{
    略
}


・Saki.cpp

extern int MaxNum;

extern void TasuIchi(int num);


こうしておくことで二重定義になることなく、他のファイルで定義されている変数や関数を使用することができる。

はじめの頃はExternなんて言葉すら知らなかったので、何時間も悩んだ。。。

【C++】_TやらLやらについて

問題

たまに見る_TやらLやらがややこしい。
文字列を扱うときに使うものというのはわかっているが、どっちが何するものかも迷う。


理解

マクロ 意味
_T("text") textのT
TEXT("text") そのまんまのtext(_Tと同じ)
L"" リテラル


T("")の使い方(TEXT("")も)

なんでも_Tはマルチバイトとユニコードの違いをなくすてきな、万能なものみたい。
そのあたりの設定に関しては、プロジェクトのプロパティに記載あり。
(構成プロパティ > 詳細 > 文字セット)
以下のように使う。

auto text = _T("text");

たまにTCHAR使えないプロジェクトがあるけど、基本的にはこれでOK。


L""の使い方

ユニコード文字列という意味を表すものみたい。
いつ使うのかいまいちわからないけど、プロジェクトとしてユニコード文字列を使うとなった時は、 以下のように文字列定義する。

auto text = L"text";


ちなみに

以下のマイクロソフトのサイト見て気づいたけど、シングルクォーテーションで囲むか、ダブルクォーテーションで囲むかで意味が違ったりするんや。。。
docs.microsoft.com

【C++】#Includeについて 1つ以上の複数回定義されているシンボルがみつかりました。

問題

いろんなクラスの関数・変数を呼ぶために#Includeを記載するが、どうやら何度も定義されている関数があるみたい。 Includeループ地獄に入ってしまった。


そもそもIncludeとは

他のクラスで宣言されている関数・変数などを今実装中の箇所でも使用するために、その関数宣言を実装箇所で認識させるためのものと思っている。
なんでもincludeすると、指定したファイルがそのまま展開されるとのことで、includeしたファイルの中でさらにincludeしているなんてことはざらにあると思われる。


解決策

pragma once

ほとんどの場合最初からこれが定義されていると思うので、これで直ることはあまりないと思うが、これを書くだけで同じヘッダーファイルは一度しか展開されなくなり、重複定義が解決できるかも。
ちなみにインクルードガードというものもあるようです。(以下のような)

#ifndef HOGE
#define HOGE
#endif

pragma onceを使っていれば不要な気がします。意味あるのか?


externを使う

そもそもincludeが必要かを考える。
externを関数や変数の頭につけると、他のファイルで宣言されている関数や変数を使うことができる。

global.h

int globalInt;

local.h

int localInt;
extern int globalInt;

上記のようにExternを使えばIncludeせずとも関数や変数が使えるようになる。

【C++】ポインタについて

問題

ポインタという言葉は知っているし、アドレスという言葉もしっているが、やっぱりポインタで悩んだ部分があったので、自分なりの理解をまとめておく。


自分なりの理解

書き方

// int型の変数
int a =10;

// int型のポインタ
int *p_a;

// int型ポインタに代入(aのアドレスが入っている)
p_a = &a;

// アドレスの先にある値(10)を取得
int b = *p_a

上記を実行すると、ポインタ変数のp_aにint型変数aのアドレスが入っているのがわかる。


なぜポインタを使うか

  • 離れたところへも変数の値を渡すことができる
    1つのクラス内で、変数や引数を用いて値のやり取りをする分にはどうしてもポインタが必要になるような場面は少ないのかもしれないが、EXEで定義されている変数の値をDLLに渡してDLLでその値をを変更してからEXEで使うようなことが必要な場合は、とても役に立つ。

  • たくさんの値をまとめて渡せる たくさんの引数を渡さないといけないようなことがあったときに、それらの値を構造体として一つにまとめて渡す方法を考えると思う。しかし、構造体を引数にして渡すと渡した先では構造体の値がコピーされたものが渡されており、そこで構造体内の値を変更しても渡し元には変更されていない元の値のままとなる。そういった場合にポインタを使うと、渡した先での変更が呼び出し元でも反映される。

構造体やクラスのポインタを渡した場合には、以下のようにアローを使って、構造体やクラス内部の値にアクセスする。

// ポインタから構造体の中の値を取得
auto val = p_struct->InnerValue;


ちなみに

ポインタの書き方が人によって様々なようで、それによってなにか別の意味があるのではと思ってしまうことがありましたが、書き方が違うだけでポインタを表すことに違いはないみたいです。
統一して。。。

int* p_int;
int * p_int;
int *p_int;