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

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

ただいまの
回答率

88.79%

c言語 ポインタについて

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 477

toyo_69

score 13

下記に記述したプログラムのポインタ部分についての疑問なのですが
このプログラムの構造でfull_adder関数においてsとcoutのポインタを使わなければ機能しない理由が分かりません。
自分自身c言語の初学者でポインタについてあまりわかっていないこともあると思います。
宣言時以外で変数に*を付けたポインタ変数は数を格納できる箱として扱う、と覚えたので意味的には同じかと思うのですが、下記のプログラム内の*を全て外して実行してみると出力されるs0〜s7の値がそれぞれ大きな値になる(s0〜s7のアドレス?)ので混乱してしまいました。
質問の書き方に関しては謝らせていただきます。見辛くて本当に申し訳ないです。
どうしても行き詰まってしまい、理解に苦しんでいます。どうかご教示お願い致します。

ソースコード↓

#include <stdio.h>
int and(int, int);//論理積を計算する関数
int or(int, int);//論理和を計算する関数
int xor(int, int);//排他的論理和を計算する関数
int bin_to_int(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7);
//2進数から10進数に変換する関数
void full_adder(int a, int b, int cin, int *s, int *cout);
//2進数の和を計算する関数(全加算器)

int main() {
    int a0, a1, a2, a3, a4, a5, a6, a7;
    int b0, b1, b2, b3, b4, b5, b6, b7;
    int c0 = 0, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0, c7 = 0;
    int s0, s1, s2, s3, s4, s5, s6, s7;
    int k, l, m;

    printf("8桁の2進数を2つ入力せよ\n");
    printf("1つ目:");
    scanf("%d %d %d %d %d %d %d %d", &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7);
    printf("2つ目:");
    scanf("%d %d %d %d %d %d %d %d", &b0, &b1, &b2, &b3, &b4, &b5, &b6, &b7);

    k = bin_to_int(a0, a1, a2, a3, a4, a5, a6, a7);
    l = bin_to_int(b0, b1, b2, b3, b4, b5, b6, b7);
    printf("入力した1つ目の10進数表現は:");
    printf("%d\n", k);
    printf("入力した2つ目の10進数表現は:");
    printf("%d\n", l);

    full_adder(a7, b7, 0, &s7, &c0);
    full_adder(a6, b6, c0, &s6, &c1);
    full_adder(a5, b5, c1, &s5, &c2);
    full_adder(a4, b4, c2, &s4, &c3);
    full_adder(a3, b3, c3, &s3, &c4);
    full_adder(a2, b2, c4, &s2, &c5);
    full_adder(a1, b1, c5, &s1, &c6);
    full_adder(a0, b0, c6, &s0, &c7);

    m = bin_to_int(s0, s1, s2, s3, s4, s5, s6, s7);
    printf("入力した2つの2進数の和は:%d %d %d %d %d %d %d %d\n", s0, s1, s2, s3, s4, s5, s6, s7);
    printf("入力された2つの2進数の和の10進数表現は:");
    printf("%d\n", m);

    return 0;
}

int and(int a, int b) {
    if ((a == 1) && (b == 1))
        return 1;
    else
        return 0;
}

int or(int a, int b) {
    if ((a == 1) || (b == 1))
        return 1;
    else
        return 0;
}

int xor(int a, int b) {
    if (a != b)
        return 1;
    else
        return 0;
}

int bin_to_int(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7) {
    int b;
    b = 128 * n0 + 64 * n1 + 32 * n2 + 16 * n3 + 8 * n4 + 4 * n5 + 2 * n6 + n7;
    return b;
}

void full_adder(int a, int b, int cin, int *s, int *cout)
{
    *s = xor(a, xor(b, cin));//2進数の和を計算する式
    *cout = or (and (a, b), and (xor (a, b), cin));//和の繰り上げを計算する式
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hayataka2049

    2019/05/15 20:26 編集

    このサイトではコードは以下のように書くことをおすすめします。
    ```c
    ここにコード
    ```
    こう書かないとインデントが消えたりマークダウンとして解釈されたり、いろいろヘンになります。
    質問は編集できるので直しておいてください。成功すればちゃんと枠の中に入るので、プレビュー見ながらやってくださいね。
    コード部分を選択してから<code>ボタンを押しても挿入できます。

    キャンセル

  • toyo_69

    2019/05/16 22:21

    恥ずかしながら失礼しました。
    直させていただきました。有難うございます。

    キャンセル

回答 2

checkベストアンサー

+1

関数の中での変数の値の変化は、ポインタを使うか、戻り値(returnで返される値)を使わないと、関数の外では影響を与えません。
例えば、
void full_adder(int a, int b, int cin, int s, int cout)
{
s = xor(a, xor(b, cin));//2進数の和を計算する式
cout = or (and (a, b), and (xor (a, b), cin));//和の繰り上げを計算する式
}
full_adder(a, b, cin, s, cout)とか、適当な数を入れて実行しても、sとcoutの値は変動しません。

あるいはグローバル変数を使う方法もありますが、これも使われる機会は少ないです。

s0などの値が大きくなってしまった原因は&などポインタ的な指示がどこかに残っていたのかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/16 22:30

    成程、ただ単にローカル変数を関数外に渡そうとしていたからおかしくなってしまっていたのですね。
    ポインタ型変数はグローバル変数のようなものなのですね。恥ずかしながら存じ上げませんでした。
    これでスッキリしました。分かりやすい解説、本当に有難うございました。

    キャンセル

  • 2019/05/16 22:55

    >ポインタ型変数はグローバル変数のようなもの
    誤解がありそう・・・アドレス渡しにすると、呼び出し元と呼び出し先でアドレスを介して同じメモリ領域を参照できるというのがミソです。
    ただの引数だと値のコピーが別のメモリ領域に格納されるので、書き換えても意味がない・・・

    キャンセル

  • 2019/05/18 17:42

    確かに似たようなものとは言っても今回の例のような関数間でデータを渡す際にはグローバル変数を用いたところでmain関数内から渡す引数がその時その時によって違いますしポインタでないと実現しませんね。ご指摘有難うございました。

    キャンセル

0

渡し元に、数値を返すためにポインタを使ってます。
ここを単純にデータを渡してしまうと、渡し元は変更されません

full_adder(a7, b7, 0, &s7, &c0);

s7 と c0 のデータはfull_adderの関数内で変更されます

#戻り値にして値を返す、というテもありますが、それはまたべつのおはなし

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/16 22:32

    ローカル変数とグローバル変数についての知識が不十分でした。
    分かりやすい回答、有難うございました。

    キャンセル

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

  • ただいまの回答率 88.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る