😃

C言語で文字数を取得するときは、sizeof(ポインタ変数)をしてはいけない

2021/07/13に公開

C言語のsizeofの使い方を正しく把握していなかった

C言語で文字列を結合する関数を自作しているときの話
新しい文字列のメモリを確保してから、そこに結合する2つの文字列を入れる感じにしようと思いました。

新しくできる結合した文字列の文字数は
結合する文字列1をA
結合する文字列2をBとすると
以下のように表せます
新しい文字列の文字数 = Aの文字数 + Bの文字数 + 1(終端文字分)
なので以下のようにメモリを確保するように記述しました。

char	*join(char const *s1, char const *s2)
{
	char	*new_str;
	new_str = (char *)malloc(sizeof(char) * (sizeof(s1) + sizeof(s2)) + 1);
}

いざ文字列が結合できているか検証..としたところ、結合した文字列が途中で切れています。
要するに、mallocで用意した文字数が少なかったのです。
なぜなのでしょうか?

sizeof(ポインタ変数)としても中身の長さはわからない

結論(sizeof(s1) + sizeof(s2))の部分が悪さをしていたようです。
以下のように検証してみます。

char	*s1 = "lorem ipsum";
printf("%lu\n", sizeof(s1));

結果は以下のようになります。

8

s1の文字列の長さは12あるはずなのに、8と出力されてしまいました。
調べて見ると、どうやらポインタ型のサイズは全ての型において32bit OSならば4byte 64bit OSならば 8byteとして出力されるようです。
なので今回のようにsizeofの引数のcharのポインタ型は中身の長さに関わらず8と出力されてしまったようです。

なので、以下のような他の型のポインタ変数やポインタ変数型を引数とした場合でも、8と出力されます。

int a = 1;
int *b = &a;
printf("%lu\n", sizeof(b));8
printf("%lu\n", sizeof(long *));8

どうやら自分がやりたかった文字列の中身の文字数の計測は、strlenなどでするのが一般的なようです。
割と初歩的なことですが、初心者はつまづきやすい箇所だと思ったので記事にしました。

参考

https://hensa40.cutegirl.jp/archives/2833
http://rainbow.pc.uec.ac.jp/edu/program/b1/Ex4-1.htm

Discussion