質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

5回答

916閲覧

Cのsizeofの結果が理解できない

ren.w

総合スコア42

char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2022/01/21 07:56

編集2022/01/21 07:56

前提・実現したいこと

文字列配列food1つ分のメモリサイズを知りたかったのでsizeofを使い確かめてみました。
結果は8と表示されたのですが理由がわかりません。
配列の中で一番多い文字数は「カレールー」「かたくりこ」の5文字です。
私はUTF-8を使用しているので一文字3バイト、/0も含めると16バイト必要なはずですよね。
それなのに何故半分の8と表示されるのでしょうか。

また、もう一点わからない点があって、food配列の「カレールー」と「かたくりこ」を消してもメモリサイズは8と表示されます。「あ」とか「い」みたいな1文字しかない要素だけにしても8と表示されます。何故でしょうか。
私はデータ型のcharは1バイトと習ったので、そこも理解できません。

該当のソースコード

c

1#include <stdio.h> 2#include <string.h> 3 4int main(void){ 5 int i=0; 6 int menu=0; 7 char* food[7]={"とりにく","カレールー","ライス","ぶたにく","かたくりこ","にんじん","トマト"}; 8 9 printf("配列1個のメモリサイズ%ld\n",sizeof food[0]); 10 11}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

food配列と各文字列のメモリ上の配置を図示します。

イメージ説明

  • char * food[7]; はポインタが7個ある配列です。64bitマシンはポインタ(アドレス)に64ビット必要なので、ポインタのサイズは8(8バイト)です。food[0] ~ food[6] 全てがポインタです。当然、いずれもサイズは8です。
  • 各文字列、UTF-8だと漢字一文字は大抵3バイトです。「とりにく」の「と」も「り」も3バイト、そして文字列の最後にはターミネータ'\0' の1バイトがあります。アスキー文字(英数字記号等)は一文字1バイトですから、各文字列の長さは文字列に応じて1バイト単位で変化します
  • food[0] ~ food[6] は各文字列をポイントしている=food[0] ~ food[6] の値は各文字列の先頭アドレスです。

メモリ上のデータ配置と値を直接見る手段はメモリダンプです。私の手元でやってみた結果を記します(GCC on Ubuntu)。手描きの図とメモリダンプを対応させてご覧ください。具体的なメモリアドレスは同じではないとしても、質問者のところでも同様のメモリ配置になっていると思います。

bash

1rubato$ cc 3tdqdpg4d3gaxu.c mdump-utf8.c 2rubato$ ./a.out 3配列1個のメモリサイズ 8, strlen = 12 4配列1個のメモリサイズ 8, strlen = 15 5配列1個のメモリサイズ 8, strlen = 9 6配列1個のメモリサイズ 8, strlen = 12 7配列1個のメモリサイズ 8, strlen = 15 8配列1個のメモリサイズ 8, strlen = 12 9配列1個のメモリサイズ 8, strlen = 9 10 'char * food[7]' 110x7ffddaa7cef0: 08 20 01 f9 53 56 00 00 15 20 01 f9 53 56 00 00 . ..SV... ..SV.. 120x7ffddaa7cf00: 25 20 01 f9 53 56 00 00 2f 20 01 f9 53 56 00 00 % ..SV../ ..SV.. 130x7ffddaa7cf10: 3c 20 01 f9 53 56 00 00 4c 20 01 f9 53 56 00 00 < ..SV..L ..SV.. 140x7ffddaa7cf20: 59 20 01 f9 53 56 00 00 00 25 ec 8a 9e 57 5c fa Y ..SV...%슞 W\. 15 'food[0] .. food[6]' 160x5653f9012008: e3 81 a8 e3 82 8a e3 81 ab e3 81 8f 00 e3 82 ab と り に く .カ 170x5653f9012018: e3 83 ac e3 83 bc e3 83 ab e3 83 bc 00 e3 83 a9 レ ー ル ー .ラ 180x5653f9012028: e3 82 a4 e3 82 b9 00 e3 81 b6 e3 81 9f e3 81 ab イ ス .ぶ た に 190x5653f9012038: e3 81 8f 00 e3 81 8b e3 81 9f e3 81 8f e3 82 8a く .か た く り 200x5653f9012048: e3 81 93 00 e3 81 ab e3 82 93 e3 81 98 e3 82 93 こ .に ん じ ん 210x5653f9012058: 00 e3 83 88 e3 83 9e e3 83 88 00 00 00 00 00 00 .ト マ ト ...... 220x5653f9012068: e9 85 8d e5 88 97 ef bc 91 e5 80 8b e3 81 ae e3 配 列 1 個 の メ

プログラムの main() 関数を次のように少し変えました。mdump() 関数は省略します。

C

1#include <stdio.h> 2#include <string.h> 3void mdump(void * addr, int size, char * title); 4 5int main(void) { 6 char * food[7] = { 7 "とりにく", "カレールー", "ライス", "ぶたにく", 8 "かたくりこ", "にんじん", "トマト" 9 }; 10 for (int i = 0; i < 7; i++) { 11 printf("配列1個のメモリサイズ %ld, strlen = %ld\n", 12 sizeof food[i], strlen(food[i])); 13 } 14 mdump(food, sizeof(food), "char * food[7]"); 15 mdump(food[0], 16 * 7, "food[0] .. food[6]"); 16}

投稿2022/01/22 01:22

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ren.w

2022/01/22 12:47

回答ありがとうございます。 図やコードまで載せて下さり非常に助かりました。
guest

0

foodchar *の配列ですので、food[0]char *です。
charへのポインタのサイズは環境によりますが、今回は8です。

投稿2022/01/21 08:00

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ren.w

2022/01/22 12:46

回答ありがとうございます。 food[0]は文字列として扱われると勘違いをしていました。
guest

0

文字列長を得たいなら、strlen関数を使いましょう

投稿2022/01/21 08:20

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ren.w

2022/01/22 12:43

ありがとうございます。 strlen関数は文字数だけ取得する関数だと思っていたのですが、メモリ数を取得してくれる関数だったのですね。
y_waiwai

2022/01/22 13:11

sizeofではポインタサイスが帰ります strlenでは文字列長が帰ります あなたが得たいのはなんでしょうか
guest

0

ポインタのサイズは8バイトです。(環境によって異なりますが、最近は8バイトが多いです)
図示すると以下のようになります。
イメージ説明

投稿2022/01/22 00:45

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ren.w

2022/01/22 12:46

回答ありがとうございます。 food[]0やfood[6]は中身の文字列でなくポインタとして扱われるのですね。
guest

0

char* food[7] てことは,配列 food の要素は char*。
sizeof(food[0]) は char* のサイズが得られるだけで、文字列の長さは得られません。

char food[] = "とりにく";
で sizeof(food) してみて。

投稿2022/01/21 08:02

編集2022/01/21 08:07
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ren.w

2022/01/22 12:43

回答ありがとうございます。 無事文字列のサイズを取得することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問