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

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

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

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

4回答

544閲覧

C言語の構造体ポインターにおいて関数先で配列が増加する場合の書き方を教えて下さい

halohalolin

総合スコア46

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2020/01/30 07:17

以下のようなC言語の構造体ポインターにおいて関数先で内容を定義するコードを書いています。
しかしながら下記コードにおけるaddStaff関数内で設定した内容がmainのstaffポインターに引き継がれず、main関数のprintfにてSegmentation fault(コアダンプ)が発生してしまいます。
参照渡しの理解が足りないのだと考えていますが、いまのところ良い参考サイトが見つけられず困っています。

ちなみに下記のコードは、staffポインターに3人の名前を定義して表示するプログラムです。
表示するのはmain関数内、人を定義するのはaddStaff関数内でお願いします。

以上、よろしくお願いいたします。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4struct _staff { 5 char name[64]; 6}; 7 8void addStaff(struct _staff *staff); 9 10int main(void) { 11 int i; 12 struct _staff *staff; 13 14 printf("start\n"); 15 addStaff(staff); 16 17 printf("result\n"); 18 for(i = 0; i < 3; i++) { 19 printf("No %d, %s\n", i+1, staff[i].name); 20 } 21 22 printf("end\n"); 23 return 0; 24} 25 26void addStaff(struct _staff *staff) 27{ 28 staff = (struct _staff *)malloc(sizeof(struct _staff) * 3); 29 sprintf(staff[0].name, "akai"); 30 sprintf(staff[1].name, "aoi"); 31 sprintf(staff[2].name, "hogehoge"); 32}

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

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

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

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

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

guest

回答4

0

addStaff関数と言う名前が気になって作成してみました。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4struct _staff { 5 char name[64]; 6}; 7 8struct _staff * addStaff(struct _staff *staff); 9 10int main(void) { 11 int i; 12 struct _staff *staff; 13 14 printf("start\n"); 15 staff=addStaff(staff); //1回目 16 staff=addStaff(staff); //2回目 17 staff=addStaff(staff); //3回目 18 19 printf("result\n"); 20 for(i = 0; i < 9; i++) { 21 printf("No %d, %s\n", i+1, staff[i].name); 22 } 23 24 free(staff); 25 printf("end\n"); 26 return 0; 27} 28 29struct _staff * addStaff(struct _staff *staff) 30{ 31 static int cnt=0; 32 int ap=cnt; 33 if ( cnt == 0 ) 34 staff = (struct _staff *)malloc(sizeof(struct _staff)); 35 cnt+=3; 36 staff = (struct _staff *)realloc(staff, sizeof(struct _staff) * cnt); 37 if ( staff == NULL ){ 38 free(staff); 39 exit(EXIT_FAILURE); 40 } 41 42 sprintf(staff[ap++].name, "akai"); 43 sprintf(staff[ap++].name, "aoi"); 44 sprintf(staff[ap++].name, "hogehoge"); 45 return(staff); 46}

投稿2020/01/30 23:11

amura

総合スコア333

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

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

halohalolin

2020/01/31 01:18

amuraさんありがとうございます。 元のソースコードは初期設定でしか名前を設定できないのにaddStaffという名前はアレだったですね。 参考にさせていただきます。
guest

0

スタッフを管理するスタッフリスト構造体を用意する手もありますよ。
それと、sprintfなどの書式指定ライブラリを使うのであれば、書式に "%s" などを必ず使ってください。フォーマットストリング攻撃される脆弱性になってしまう可能性がありますので。
単に文字列をコピーするのであれば strcpy を使うといいです。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4typedef struct staff { 5 char name[64]; 6} staff_t; 7 8typedef struct stafflist { 9 int num; 10 staff_t *staff; 11} stafflist_t; 12 13void addStaff(stafflist_t *stafflist); 14 15int main(void) { 16 int i; 17 stafflist_t stafflist; 18 19 printf("start\n"); 20 addStaff(&stafflist); 21 22 printf("result\n"); 23 for(i = 0; i < stafflist.num; i++) { 24 printf("No %d, %s\n", i+1, stafflist.staff[i].name); 25 } 26 27 printf("end\n"); 28 return 0; 29} 30 31void addStaff(stafflist_t *stafflist) 32{ 33 int num = 3; 34 staff_t *staff = (staff_t *)malloc(sizeof(staff_t) * num); 35 sprintf(staff[0].name, "%s", "akai"); 36 sprintf(staff[1].name, "%s", "aoi"); 37 sprintf(staff[2].name, "%s", "hogehoge"); 38 stafflist->num = num; 39 stafflist->staff = staff; 40}

ちょっと脱線しますが、C++だとこんな書き方ができます。

c++

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5struct Staff { 6 char name[64]; 7}; 8 9struct StaffList { 10 int num = 0; 11 Staff *staff = NULL; 12 13 void add(const char *name) { 14 staff = (Staff *)reallocarray(staff, sizeof(Staff), num + 1); 15 strncpy(staff[num].name, name, sizeof(staff[num].name) - 1); 16 num++; 17 } 18}; 19 20int main(void) { 21 printf("start\n"); 22 23 StaffList stafflist; 24 stafflist.add("akai"); 25 stafflist.add("aoi"); 26 stafflist.add("hogehoge"); 27 28 printf("result\n"); 29 for(int i = 0; i < stafflist.num; i++) { 30 printf("No %d, %s\n", i+1, stafflist.staff[i].name); 31 } 32 33 printf("end\n"); 34 return 0; 35}

投稿2020/01/30 08:06

編集2020/01/31 03:14
shiracamus

総合スコア5406

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

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

halohalolin

2020/01/30 08:12

shiracamusさん、ありがとうございます!
guest

0

ベストアンサー

他の回答のように戻り値で受け取る方法もありますが、現在のコードを利用する場合、引数をダブルポインタにする必要があります。
どこが変わったかはご自分で差分で見てみてください。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4struct _staff { 5 char name[64]; 6}; 7 8void addStaff(struct _staff **staff); 9 10int main(void) { 11 int i; 12 struct _staff *staff; 13 14 printf("start\n"); 15 addStaff(&staff); 16 17 printf("result\n"); 18 for(i = 0; i < 3; i++) { 19 printf("No %d, %s\n", i+1, staff[i].name); 20 } 21 22 printf("end\n"); 23 return 0; 24} 25 26void addStaff(struct _staff **staff) 27{ 28 *staff = (struct _staff *)malloc(sizeof(struct _staff) * 3); 29 sprintf((*staff)[0].name, "akai"); 30 sprintf((*staff)[1].name, "aoi"); 31 sprintf((*staff)[2].name, "hogehoge"); 32}

投稿2020/01/30 07:41

ttyp03

総合スコア16998

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

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

halohalolin

2020/01/30 07:58

ttyp03さん、ありがとうございます! 実は先のコードはあくまでサンプルで、実際悩んでいるコードが別にあります。 そこで、コードの修正が少なくてすみそうなttyp03さんの案で試してみたところ、動作を確認しました! ダブルポインターとかまったく理解の外にあったので、精進させていただきます。 素早いご返答ありがとうございました!
guest

0

C

1void addStaff(struct _staff *staff)

これではポインタはコピーされるので、staff = (後略);と関数内で代入しても、その値はどこにも影響せずに無効になってしまいます。

ポインタを返り値にして、呼ぶ側でstaff = addStaff();のように受け取れるようにする、というのが適切です。

投稿2020/01/30 07:19

maisumakun

総合スコア145184

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

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

halohalolin

2020/01/30 08:00

maisumakunさん、ありがとうございます。 実は先のコードはサンプルで、実際悩んでいるコードが別にあります。 そこで、コードの修正が少なくてすみそうな別の方(ttyp03さん)の案で進めようと考えています。 maisumakunさんの案も今後別の機会に使えるよう、糧にさせていただきます。 素早いご返答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問