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

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

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

Clangは、プログラミング言語 C、C++、Objective-C、Objective-C++ 向けのコンパイラである。

Q&A

2回答

1168閲覧

C言語におけるポインタを用いたスタックの実装

kez_yuyuyu

総合スコア9

Clang

Clangは、プログラミング言語 C、C++、Objective-C、Objective-C++ 向けのコンパイラである。

0グッド

0クリップ

投稿2022/05/28 08:15

編集2022/05/28 08:16

解決したいこと

  • 勉強をしていて、配列を用いることでスタックを実装できることを知りました。
  • そこで配列の代わりにポインタを使うことでも実装できるのではないかということで実装を試しました。
  • しかしどうしてもうまくいかないため、どうしたらうまくいくのか教えていただきたいです。

ソースコード

//ポインタを用いた実装 # include <stdio.h> int stack[8]; //ポインタ変数の宣言 int *head; //配列の先頭のポインタを代入 head = &stack[0]; //pop関数の実装(値を取り出す) int pop(){ int pop_num = *head; head = head-sizeof(stack[0]); return pop_num; } //push関数の実装(値の追加) void push(int a){ head = head + sizeof(stack[0]); *head = a; } int main(){ push(1); push(2); int ans = pop(); printf("%d",ans); push(3); int ans_2 = pop(); printf("%d",ans); return 0; }

やりたいこと

  1. まず配列を指定します。
  2. 次に[0]のポインタを取得して、それを保持します
  3. popの関数が呼ばれると、保持しているポインタから値を取り出し、int分ポインタの値を下げます
  4. pushが呼ばれたときはint型の引数を受け取り、ポインタの値をint分増加したのち、値を格納します。

エラーメッセージ

point.c:8:1: warning: data definition has no type or storage class 8 | head = &stack[0]; | ^~~~ point.c:8:1: warning: type defaults to 'int' in declaration of 'head' [-Wimplicit-int] point.c:8:1: error: conflicting types for 'head'; have 'int' point.c:6:6: note: previous declaration of 'head' with type 'int *' 6 | int *head; | ^~~~ point.c:8:8: warning: initialization of 'int' from 'int *' makes integer from pointer without a cast [-Wint-conversion] 8 | head = &stack[0]; | ^ point.c:8:8: error: initializer element is not computable at load time point.c: In function 'pop': point.c:12:19: error: invalid type argument of unary '*' (have 'int') 12 | int pop_num = *head; | ^~~~~ point.c: In function 'push': point.c:20:5: error: invalid type argument of unary '*' (have 'int') 20 | *head = a; | ^~~~~

補足説明

  • 今回のコードは空かどうか、満タンかどうかを判断する関数を実装していないので、pushした後にpopができればいいものとします。

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

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

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

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

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

y_waiwai

2022/05/28 08:21

で、しつもんはなんでしょうか
hoshi-takanori

2022/05/28 08:22

> 配列の代わりにポインタを使う そのコードでも配列は使ってるので、「添字の代わりにポインタを使う」でしょうか? エラーの原因は実行文を関数の外に書いてるからですね。 あと、ポインタのインクリメント・デクリメント幅が大きすぎるような…。
kez_yuyuyu

2022/05/28 08:26

>>「添字の代わりにポインタを使う」でしょうか? はいその通りです。分かりにくくて申し訳ございません。 main関数の中に記載するということでしょうか? グローバル変数にしたかったので外に書いたのですがそれが不味かったということでしょうか? またint型で指定しているので4バイト分動かせばいいと考えたのですが大きいのはなぜですか?
hoshi-takanori

2022/05/28 08:59 編集

宣言と代入を分けてるので、関数の外では代入がエラーになります。宣言と初期化を同時に行えば大丈夫なはず。 また、よくある間違いですが、ポインタの足し算や引き算は、ポインタの指す型のサイズ倍されます。ので、単純に 1 足したり引いたりすれば良いのです。もっと言うと ++ や — を 1 回で大丈夫です。 https://www.ei.fukui-nct.ac.jp/2019/05/21/pointer-array/
guest

回答2

0

まず、Cのプログラムを書く前に、Cの文法を学習しましょう。

・実行文を関数の外に書いている。
・変数名を間違っている
{ }の対応が間違っている
の3点がまず文法的におかしいです。

次に、ポインターを使ったプログラムを書く前に、ポインターについて学習しましょう。
あと、int *head;とポインターとして宣言した変数に+ 1すると実際には変数の中のアドレス値はsizeof(int)文だけ増えます。
つまり、intサイズが4の場合、head++;で4増えます。head = head + sizeof(stack[0]);すると4*4で16増えます。

投稿2022/05/28 08:58

otn

総合スコア84645

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

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

kez_yuyuyu

2022/05/28 09:15

>>>変数名を間違っている,{ }の対応が間違っている 具体的にはどこがちがっているのでしょうか? もう一度ポインタについて学びたいと思います
otn

2022/05/28 09:51 編集

変数はたかだか数個しか無いので、見たらわかるのでは?見てないのでしょうか? あるかどうかわからない間違いを探すのは大変ですが、絶対にあるとわかっている間違いの発見は、順番に見ていけば良いだけなので、簡単です。
guest

0

とりあえずコンパイルエラーの指摘を。

head = &stack[0];

実行文は関数の中に書きましょう
あるいは、初期化式とします

int* head = &stack[0];

投稿2022/05/28 08:37

y_waiwai

総合スコア87784

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

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

kez_yuyuyu

2022/05/28 08:51

先頭でint *head;と指定しているのですがそれではダメなのですか?
y_waiwai

2022/05/28 08:58

そうするなら、代入文は関数の中に記述して実行する必要があります
y_waiwai

2022/05/28 09:02

int* head = &stack[0]; とにかくその行をこれに変えてみよう
kez_yuyuyu

2022/05/28 09:03

ありがとうございます!やってみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問