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

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

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

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

ポインタ

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

関数

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

Q&A

解決済

2回答

1373閲覧

構造体のポインタ変数を引数に持つ関数について

mayjex

総合スコア1

C

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

ポインタ

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

関数

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

0グッド

0クリップ

投稿2021/08/28 09:27

前提

C言語を学習している初学者です。
現在構造体の学習をしており、構造体のポインタ変数を引数に持つ関数を作成し、
デバックを行ったのですが、エラーが発生してしまい原因が分からず困っています。
原因がお分かりの方がいらっしゃいましたらご教授いただきたいです。
宜しくお願いします。

該当のソースコード

C言語

1#include <stdio.h> 2#include <string.h> 3 4// 学生情報を入れる構造体 5typedef struct { 6 int id; // 学生番号 7 char name[256]; // 氏名 8 int age; // 年齢 9} student_data; 10 11// 学生情報を構造体に格納する関数 12void setData(student_data*, int, char*, int); 13// 学生情報を表示する関数 14void showData(student_data*); 15 16void main() { 17 int i; 18 student_data* data[4]; 19 int id[] = { 1, 2, 3, 4 }; 20 char name[][256] = { "山田", "佐藤", "太田", "中田" }; 21 int age[] = { 18, 19, 21, 18 }; 22 // 学生情報をセット 23 for (i = 0; i < 4; i++) { 24 setData(&data[i], id[i], name[i], age[i]); 25 } 26 // 学生情報を表示 27 for (i = 0; i < 4; i++) { 28 showData(&data[i]); 29 } 30} 31 32void setData(student_data* data, int id, char* name, int age) { 33 data->id = id; 34 strcpy(data->name, name); 35 data->age = age; 36} 37 38void showData(student_data*data) { 39 printf("学生番号:%d ", data->id); 40 printf("氏名:%s ", data->name); 41 printf("年齢:%d\n", data->age); 42}

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

デバックを実行すると、

例外がスローされました Run-Time Check Failure #2 - Stack around the variable 'data' was corrupted.

と表示されます。

また、標準出力も以下のように学生番号1~3の氏名がおかしな表示になってしまいます。

学生番号:1 氏名: 年齢:18 学生番号:2 氏名: 年齢:19 学生番号:3 氏名: 年齢:21 学生番号:4 氏名:中田 年齢:18

補足情報(FW/ツールのバージョンなど)

開発環境はVisual studio 2019を使用しています。

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

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

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

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

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

guest

回答2

0

student_data* data[4];

これはstudent_data構造体を指すポインタが4個の配列を定義しています。
しかし、その4つのポインタが指すべき、student_data構造体の「実体」は定義されていないようです。
各ポインタの値は初期化されておらず不定ですので、それらのポインタでデータを読み書きするということは、つまり不定のアドレスに対してアクセスしていることになります。当然例外が引き起こされます。


よく見ると、それらのポインタの値での読み書きはしておらず、それらのポインタ変数のアドレスを渡しているので、ポインタ変数が自体のアドレスをstudent_data構造体のアドレスとみなしてそのメンバーにアクセスしていることになりますね。いずれにしてもそれは誤りです。

投稿2021/08/28 09:36

編集2021/08/28 09:40
itagagaki

総合スコア8402

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

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

mayjex

2021/08/28 09:50

ご回答ありがとうございます。 "student_data*data[4]"という定義だと、構造体を指すポインタを4つ格納する配列という意味になるということですね。 やりたかったこととしては、構造体を4つ格納する配列という意味で定義したかったので"student_data data[4]" とするのが正しいと理解しました。ありがとうございました。
guest

0

ベストアンサー

student_data* data[4]; の*を外して

student_data data[4];

とするだけでOK.

さもなくば:

C

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4 5// 学生情報を入れる構造体 6typedef struct { 7 int id; // 学生番号 8 char name[256]; // 氏名 9 int age; // 年齢 10} student_data; 11 12// 学生情報を構造体に格納する関数 13void setData(student_data*, int, char*, int); 14// 学生情報を表示する関数 15void showData(student_data*); 16 17void main() { 18 int i; 19 student_data* data[4]; 20 int id[] = { 1, 2, 3, 4 }; 21 char name[][256] = { "山田", "佐藤", "太田", "中田" }; 22 int age[] = { 18, 19, 21, 18 }; 23 // 学生情報をセット 24 for (i = 0; i < 4; i++) { 25 data[i] = (student_data*)malloc(sizeof(student_data)); // ※追加 26 setData(data[i], id[i], name[i], age[i]); // ※ &data[i] → data[i] 27 } 28 // 学生情報を表示 29 for (i = 0; i < 4; i++) { 30 showData(data[i]); // ※ &data[i] → data[i] 31 free(data[i]); // ※追加 32 } 33} 34 35void setData(student_data* data, int id, char* name, int age) { 36 data->id = id; 37 strcpy(data->name, name); 38 data->age = age; 39} 40 41void showData(student_data*data) { 42 printf("学生番号:%d ", data->id); 43 printf("氏名:%s ", data->name); 44 printf("年齢:%d\n", data->age); 45}

※ なぜだかわかるかな?

投稿2021/08/28 09:32

編集2021/08/28 09:38
episteme

総合スコア16612

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

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

mayjex

2021/08/28 09:42

ご回答ありがとうございます。 教えていただいた方法で正常に動作しました。 *を外したら良い理由ですが、 構造体の配列自体がポインタを表しているため、*data[4]としてしまうと、 ポインタのポインタになってしまうからという認識であってますでしょうか? (説明がわかりにくくてすいません。)
episteme

2021/08/28 09:45 編集

てか、*付いた状態でコンパイルしたらwarning出たんじゃありません?
mayjex

2021/08/28 09:52

warningは出ていませんでした。
episteme

2021/08/28 09:54 編集

あれー? 僕とこと違うなー... > foo.c(26): warning C4047: '関数': 間接参照のレベルが 'student_data *' と 'student_data **' で異なっています。 > foo.c(26): warning C4024: 'setData': の型が 1 の仮引数および実引数と異なります。 ...って叱られたんだけどなー
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問