C言語
前回、C言語での条件分岐としてif文を学びました。
今回はfor文を学んだ時に出てきたリスト内の要素数を数える「sizeof(str_list)/sizeof(str_list[0])」を詳しく見ていきたいと思います。
Pythonでのリスト内の要素の数え方
まずはPythonでのリスト内の要素の数え方を見てみましょう。
Pythonの場合はlen関数を使い、「len(リスト名)」によりリスト内の要素の数を数えることができました。
num_list = [1, 2, 3, 4, 5]
print(len(num_list))
実行結果
5
ちなみにlen関数は文字列の長さを数えたりもできる便利な関数です。
str1 = 'str1'
print(len(str1))
実行結果
4
こんな感じでPythonでは簡単に数を数えるとうことができます。
C言語での数える関数 sizeof関数
C言語での数える関数は「sizeof(数える対象)」です。
とりあえず5つの整数を格納したリストで試してみましょう。
#include <stdio.h>
int main(void)
{
int i[5] = {1, 2, 3, 4, 5};
printf("%d", sizeof(i));
}
実行結果
sizeof1.c:7:18: warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]
printf("%d", sizeof(i));
~~ ^~~~~~~~~
%lu
1 warning generated.
20
warning(警告)が出ました。
この警告としてはprintf関数で出力する際、int型である「%d」で出力してしまったことに起因します。
警告文をよく読むと「unsigned long」、つまり「%ul」で出力するように書かれています。
試してみましょう。
#include <stdio.h>
int main(void)
{
int i[5] = {1, 2, 3, 4, 5};
printf("%lu", sizeof(i));
}
実行結果
20
エラーは出なかったものの、結果は「20」と表示されました。
なぜ「20」なのでしょうか?
それではリスト内の要素一つの長さを出力してみましょう。
#include <stdio.h>
int main(void)
{
int i[5] = {1, 2, 3, 4, 5};
printf("%lu", sizeof(i[0]));
}
実行結果
4
今度は「4」と出力されました。
ここで思い出すのは、各データ型の性質です。
こちらの記事で紹介しましたが、データ型によって何 Byteの長さのデータを使っているのかが異なります。
そしてint型においては、環境によって2 Byteか4 Byteかが自動で選択されるとのことでした。
私の環境ではint型は4 Byteとなっているため、先ほどの数字の長さが「4」と表示されたということです。
そうなると最初にリストの長さを出力した際「20」と出力されたこともうなづけることでしょう。
つまり「各要素の長さ4 x 要素5つ = 20」というわけです。
ここまでくると「sizeof(str_list)/sizeof(str_list[0])」が分かってきます。
つまり「リスト全体のByte数/リスト内の要素の長さのByte数」であり、この計算により「リスト内の要素の数」となるというわけです。
他のデータ型でも試してみましょう。
まずは各データ型を含んだ要素を作り、その要素の長さを出力してみます。
#include <stdio.h>
int main(void)
{
char c[5] = {'a', 'b', 'c', 'd', 'e'};
short s[5] = {1, 2, 3, 4, 5};
long l[5] = {1, 2, 3, 4, 5};
float f[5] = {1, 2, 3, 4, 5};
double d[5] = {1, 2, 3, 4, 5};
printf("%lu\n", sizeof(c[0]));
printf("%lu\n", sizeof(s[0]));
printf("%lu\n", sizeof(l[0]));
printf("%lu\n", sizeof(f[0]));
printf("%lu\n", sizeof(d[0]));
}
実行結果
1
2
8
4
8
char型は「1」、short型は「2」、long型は「8」、float型は「4」、double型は「8」ということで前に学んだデータ型の長さと合います。
これらを使ってそれぞれの要素の数を数えてみましょう。
#include <stdio.h>
int main(void)
{
char c[5] = {'a', 'b', 'c', 'd', 'e'};
short s[5] = {1, 2, 3, 4, 5};
long l[5] = {1, 2, 3, 4, 5};
float f[5] = {1, 2, 3, 4, 5};
double d[5] = {1, 2, 3, 4, 5};
printf("%lu\n", sizeof(c)/sizeof(c[0]));
printf("%lu\n", sizeof(s)/sizeof(s[0]));
printf("%lu\n", sizeof(l)/sizeof(l[0]));
printf("%lu\n", sizeof(f)/sizeof(f[0]));
printf("%lu\n", sizeof(d)/sizeof(d[0]));
}
実行結果
5
5
5
5
5
それぞれリスト内の要素数である「5」が表示され、どのデータ型でもこのような計算で要素の数が取得できることが分かりました。
文字列のリストの要素数と要素の長さ
先ほど色々なデータ型で要素の長さとリスト内の要素の数を出力してみましたが、文字列だけは省いていました。
もちろん文字列も同じようにして要素の長さ、リスト内の要素の数を出力できます。
#include <stdio.h>
int main(void)
{
char c[5][5] = {"str1", "str2", "str3", "str4", "str5"};
printf("%lu\n", sizeof(c));
printf("%lu\n", sizeof(c[0]));
printf("%lu\n", sizeof(c)/sizeof(c[0]));
}
実行結果
25
5
5
確かに問題なく数えることができました。
ちなみに要素の数が4文字なのに「5」と表示されているのは、終端文字「\0」を含んでいるからです。
ただ文字列を定義する際、文字列よりも長い場所を確保することができました。
#include <stdio.h>
int main(void)
{
char a[4];
a[0] = 'x';
a[1] = 'y';
a[2] = '\0';
printf("%s", a);
}
実行結果
xy
ということで代入する文字列よりも大きな場所を確保した場合、要素の長さはどう出力されるの試してみましょう。
#include <stdio.h>
int main(void)
{
char c[5][10] = {"str1", "str2", "str3", "str4", "str5"};
printf("%lu\n", sizeof(c));
printf("%lu\n", sizeof(c[0]));
printf("%lu\n", sizeof(c)/sizeof(c[0]));
}
実行結果
50
10
5
要素の長さは「10」と表示されました。
このことからsizeof関数では、代入された要素の長さではなく、確保した場所の長さが出力されるということが分かりました。
では文字列の長さを知りたい時はどうするのでしょうか。
その場合は、string.hのstrlen関数を使用します。
#include <stdio.h>
#include <string.h>
int main(void)
{
char c[5][10] = {"str1", "str2", "str3", "str4", "str5"};
printf("%lu\n", strlen(c[0]));
}
実行結果
4
結果として「4」と出力されたことから、strlen関数は終端文字を含まない文字列の長さを返すことが分かりました。
これでC言語の基本を大まかにですが学べたかなと思います。
ということで次回からM5stickCのプログラム例を見て、M5stickCへのプログラミングを勉強していきましょう。
ではでは今回はこんな感じで。
コメント