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

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

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

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

Q&A

解決済

5回答

8446閲覧

ポインタのバイト数について

michiaki

総合スコア29

C

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

0グッド

0クリップ

投稿2017/05/10 12:02

###前提・実現したいこと

構造体で、char型をポインタで宣言した場合って4byteになるんでしょうか?

###発生している問題・エラーメッセージ

特にエラーはなし。

###該当のソースコード

C

1struct hoge{ 2 int a; 3 int b; 4 int c; 5 char *name; 6}; 7 8struct hoge data; 9data.a = 1; 10data.b = 1; 11data.c = 1; 12data.name = "hoge"; 13 14 15 16printf("%d\n",sizeof(hoge)); 17printf("%d\n",sizeof(data.name));

###試したこと

  • ポインタのサイズが4byteになっている。
  • 下記のプログラムの出力結果が
    16
    4
    となっていました。
  • 構造体の説明では、よく配列で範囲を決めた使い方が紹介されていますが
    ポインタを使うと4byte固定になるなら、こちらの方が簡単だからですか?
    まああらかじめ文字の入力がわかっているなら配列の方がいいのかなと

も思いますが。

もしかして根本的に間違っているかもしれません。

###補足情報(言語/FW/ツール等のバージョンなど)
bcc5.5 c++版

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

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

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

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

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

guest

回答5

0

こんにちは。

ポインタを使うと4byte固定になるなら、こちらの方が簡単だからですか?

まああらかじめ文字の入力がわかっているなら配列の方がいいのかなと
も思いますが。

文字数があらかじめ分かっているなら配列の方が良いかも知れません。極端な話最大3文字しか要らないなら、最後のNULL文字を含めて4バイトあれば記録できるので配列を選択するべきでしょう。

しかし、分かっていない場合は、もしかすると、超レアケースで2,000,000文字とか入れることも有るのかも知れないです。するとめったに発生しない時のことを考慮して2MBytesもの配列を確保しておくのはいくらなんでも勿体ないわけです。
そのような時は、ポインタにしておき、必要に応じて適切なサイズのメモリを確保するという使い方が多いです。

このようにどちらが好ましいかはケースバイケースです。

投稿2017/05/10 13:33

Chironian

総合スコア23272

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

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

michiaki

2017/05/14 11:50

自分も配列=ポインタなんで、結局扱いやすい配列でいいやと思い、あまり考えずに配列を使用していました。やはり深い部分の違いを考え、使い分ける必要があるのですね。勉強になります。
guest

0

ポインタのサイズが4byteになっている。

環境によります。
32bit環境では4バイト、64bit環境では8バイトになります。
構造体の中か外かというのは関係ありません。

下記のプログラムの出力結果が

構造体全体のサイズについては、先日ちょうど良い質問をされている方がいたので紹介しておきます。
https://teratail.com/questions/75460

構造体の説明では、よく配列で範囲を決めた使い方が紹介されていますが

これは言っている意味が良くわかりません。
ポインタ宣言で4バイト確保されるなら、そこに4文字分入れられる、という考え方でしょうか。
それはもちろん可能ですが、コード上アドレス値として扱う変数に文字を入れても、処理が面倒になるだけなので何のメリットもありません。
またそういうトリッキーなことをやると、可読性が悪くなります。

投稿2017/05/10 23:59

ttyp03

総合スコア16998

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

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

michiaki

2017/05/14 11:44

C言語の構造体の説明で、char型が[200]ぐらいの大きさで宣言していることが多く、違う本でchar型のポインタで入力しているのを見て、これなら何文字でも入るみたいだなと関心しました。 本を読んでいると、printf関数は、与えられた文字列の先頭のアドレスを返しているだけと書いてあったので、一々適当な値を代入しなくてもいいのかと考えました。
ttyp03

2017/05/14 23:40

解決済みですが、気になるコメントがあったので補足しておきます。 >ポインタで入力しているのを見て、これなら何文字でも入るみたいだなと関心しました。 ポインタはあくまでもアドレスを指す変数です。 なので、char型のポインタを宣言しただけで大きな領域が使えるわけではありません。 char *p; p[199] = 1; // これはできない 通常はmalloc等で動的にメモリを確保し、そのアドレスを割り当てて使います。 char *p = (char*)malloc(200); p[199] = 1; // これはOK もしくは[200]などで確保された変数のアドレスを割り当てることで、同じ領域を指す変数として使うことができます。 char a[200]; char *pa = a; pa[199] = 1; // これはOK。a[199]と同じ意味
michiaki

2017/05/15 10:03

そうですよね。枠を設定しないと、入れる文字の大きさが決まらないですね。 メモリの動的確保のところがよくわからなったので、勉強になりました。 しかし、あらかじめ入れたい文字数を想定して、大きめのサイズを確保しないといけないのですね? なんか効率が悪い気もします。
ttyp03

2017/05/15 14:59

そうですね、C言語は文字列の処理が苦手と言ってもいいでしょう。 しかし実際のプログラミングで文字列を可変で扱うということはあまりないので、それほど困らなかったりします。 また予め決まった文字列を定義しておく場合は以下のように書けるので、バイト数も気にする必要はありません。 char msg[] = "Hello World!"; // これでmsgは13バイト確保される
guest

0

ポインタ型のサイズはメモリ空間の大きさに依存します。32ビットプログラムならば32ビット、この場合4バイトとなります。64ビットならば当然倍です。定まっていないのは、C言語の文法で定められているわけではないためです。

一番下の質問はよくわかりません。が、「構造体データのやりとりにポインタを経由することが多い」という意味ならば、これは明確な有効性があります。サイズの大きい構造体データを丸ごとコピーする際には「機械語レベルでは」複数の処理が必要となります。データの受け渡しにはCPU内の記憶領域「レジスタ」を用いるわけですが、これの容量に収まらないデータは一度に処理できません(つまり、複数に分けて処理をする必要がある)これに対して、メモリ番地のデータであれば、(この場合は)固定4バイトなので、一回で処理を進めることができます。

投稿2017/05/10 14:56

HogeAnimalLover

総合スコア4830

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

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

michiaki

2017/05/14 11:59

機械語レベルでの違いまで存在するのですね。確かにポインタの方が、配列より使いやすいですね。なるほどポインタのほうがいいと明確にわかりました。
guest

0

ベストアンサー

それぞれの長さを出力しました。

c

1#include <stdio.h> 2#include <string.h> 3 4struct hoge{ 5 int a; 6 int b; 7 int c; 8 char *name; 9}; 10 11int main(void){ 12 13struct hoge data; 14data.a = 1; 15data.b = 1; 16data.c = 1; 17data.name = "hoge1"; 18 19printf("構造体: %d\n",sizeof(struct hoge)); 20printf("int a: %d\n",sizeof(data.a)); 21printf("int b: %d\n",sizeof(data.b)); 22printf("int c: %d\n",sizeof(data.c)); 23printf("ポンタ長: %d\n",sizeof(data.name)); 24printf("文字列長: %d\n",strlen(data.name)); 25 26return 0; 27} 28 29#結果 30構造体: 24 31int a: 4 32int b: 4 33int c: 4 34ポンタ長: 8 35文字列長: 5 36

ポインタは64環境なので8バイトになっています。
文字は分かり易く5文字しています。
構造体は明細の合計と合いませんが、これはメモリ上に変数が取られるときは、
アドレスが、ある決められた区切りに合わせられます。これを「バイト境界」と呼びます。
構造体はこれにより、適当にメンバ間に空間が入れられます。構造体の「アライメント」と言います。

投稿2017/05/10 14:27

A.Ichi

総合スコア4070

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

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

michiaki

2017/05/14 11:47

そんな境界があったのですね。C言語も深いところまで勉強になります。
michiaki

2017/05/14 12:02

私のプログラムで調べていただき、また違う考え方まで教えていただいたので、ベストアンサーにさせていただきます。毎回思うのですが、ベストアンサーをいろんな人につけれるようにしてほしいです。
guest

0

ポインタのサイズは4byteです。
これはアドレスの表現が4byteだからです。
そのため、プログラムのメモリ上の位置を記憶しておくのに4byte必要ということになります。
(これは32bitプログラムだからで、64bitプログラムだとポインタは8byteになります。)


構造体の説明で配列が使われない理由…ですか。
たぶん、配列を使った場合値をコピーしなくてはならないから、ではないでしょうか。

構造体の外で生成された文字列の参照を持てばよいだけの場合は、ポインタにすると簡単です。
構造体でも配列を使うことはありますが、配列を確保すればその分だけ構造体は大きくなってしまいます。
そのうえ、文字数には制限も生まれます。

配列は文字列を保持するために、その値をコピーする必要があります。
普通は下記のように初期化時に設定することができますが…

char s[100] = "Hello World!\n";

たしか、構造体内だと初期化では設定できなかった気がしますし
初期化以外ではそもそも下記のように明示的にコピーしなければなりません。

char s[100]; strcpy(s, "Hello World!\n");

指定された配列の長さを超えると構造体のデータが壊れてしまいますし、なかなか取り扱いが難しいのです。

一方、下記のようにあらかじめどこかにあるい文字列の位置を覚えておくだけでよい場合は
ポインタさえ持っていればいいことになります。

const char *s = "Hello World!\n";

なので、大抵構造体の説明ではポインタだけ持っているんだと思いますね。

投稿2017/05/10 12:35

haru666

総合スコア1591

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

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

michiaki

2017/05/14 11:56

C言語の文字は1byteづつの処理になれるので、コピーとかはstrcpyとか使わないとダメなんですね。 自分もあまりここまで考えていなかったので、勉強になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問