アプリ版:「スタンプのみでお礼する」機能のリリースについて

私は、ポインタのメリット・デメリットを以下のように考えています。

◆メリット
メモリを多く確保しなければならないオブジェクトについて、コピー処理を行うことなく省メモリでインタフェースできる。

◆デメリット
・関数内でしか使用しない非ポインタのローカル変数に比べ、
 アクセス可能な場所が多くなってしまい、色んな箇所から値が変更されうる。(影響範囲の限定がしずらい)
・可読性が低くなる。(若いエンジニアはCの経験者は少なくっていくと思われるため、保守コストが若干割高になる)

そのため、よっぽどメモリを多く使うようなオブジェクトでなければ、
(もしくは速度を重視する必要があるプログラムでなければ)
値渡しにしても良いのではと考えています。

しかし、度々目にするソースは、何でもかんでもポインタで処理しているものも多々見受けられます。
特に、int型のようなメモリを大量に使用しないものでも、ポインタで変数宣言しているケースもよく見ます。

なぜなのでしょうか?
(熟練のC言語プログラマが、昔ながらの記述を踏襲しているというのはあるのかなと考えていますが)

A 回答 (14件中11~14件)

C言語の関数では、そのアウトプットを返却値でしか受け取れないのです。


なので、関数が複数のデータを出力させたい場合は、
(1)書き込み先アドレスを渡してそこに書き込んでもらうか、
(2)構造体にまとめて一つの変数としてリターンしてもらうか、
(3)おぞましくもグローバル変数に書き込んでもらうか、
そんなところになるかと思います。

そして関数の返却値は、たいていは処理が正常に終了したかどうか等のコードで
使用されてしまいますから、それ以外のデータを受け取る場合は、
(1)の手段、つまり関数の引数にポインタを使用することになります。
    • good
    • 0
この回答へのお礼

>C言語の関数では、そのアウトプットを返却値でしか受け取れないのです。

なんと!そうだったのですか!
他の回答者様の内容なども、しっくりきました。

だからポインタ渡し、参照渡しをよく見かけていたのですね。。

お礼日時:2013/07/02 23:33

>特に、int型のようなメモリを大量に使用しないものでも、ポインタで変数宣言しているケースもよく見ます。



あなたの「よく見かける」というのは

関数内の変数でint型1個分のために

int *a = malloc(sizeof(int));

のようなポインタを使ってるのをよく見かけるということでしょうか?
私はintオブジェクトを簡易的にあらわすのに使うときもありますが、そういうケース以外でただ1個分のint型を使うのにわざわざポインタで扱うのを私は見たことありませんけど。

もしかして変数といってるのは仮引数のことで

void foo(int *a);

のようなものを、よく見かけるだったりしませんか?

この回答への補足

int *a = malloc(sizeof(int));
のケースも見ます。

ただこれに関しても、理由はあまりわかっていません。
intは、32767 ~ -32768 と決まっているのだから、サイズの確保のため、なぜわざわざmallocで書くのでしょうか?

宜しくお願いいたします。

補足日時:2013/07/02 23:31
    • good
    • 0
この回答へのお礼

No.9での回答、とても参考になりました。
ありがとうございます!

お礼日時:2013/07/05 00:27

たとえばこんなの↓、ポインタなくては書けません。



#include <stdio.h>

/*
 *nに1を加える関数
 */
void increment(int* n) { ++(*n); }

int main() {
int n = 123;
increment(&n);
printf("%d\n", n);
return 0;
}

この回答への補足

※まだ勉強中の身なので、自信はないのですが、

void increment(int &n) { n = n + 1; }

int main() {
int n = 123;
increment(n);
printf("%d\n", n);
return 0;
}

でも可能ですか?
また、ポインタで書く場合と、参照で書く場合で、どのようなメリット・デメリットの差があるのでしょうか?

補足日時:2013/07/02 23:28
    • good
    • 0
この回答へのお礼

とりあえず、私が参画するようなプロジェクトは、
期間内・予算内で、企業の利益につながるシステムを作ることが目的であるため、
インクリメント等は、別に1行でなくてもよかったり、
多少、使用メモリが多くても、まったく問題ないため、
このケースに関してはですが、ポインタにこだわる必要はないさそうです。

しかし、ポインタを使うと、色々簡潔にかけたりするのでしょうね。
ありがとうございます。

お礼日時:2013/07/05 00:31

ここで述べられているのは、関数の引数としてポインタを使う場合のことですね?



> ・関数内でしか使用しない非ポインタのローカル変数に比べ、
>  アクセス可能な場所が多くなってしまい、色んな箇所から値が変更されうる。(影響範囲の限定がしずらい)
> ・可読性が低くなる。(若いエンジニアはCの経験者は少なくっていくと思われるため、保守コストが若干割高になる)

関数にポインタを渡しても、アクセス可能な場所は限られます。
funcA(&x) としたら、xにアクセスできるのは funcAと、funcAの中で呼ばれる関数だけです。無関係な関数まで気にする必要はありません。


funcAの中でfuncBに渡され...となるとわからなくなる、というのなら、まずは、関数の仕様だけに注目することです。
funcBの実装はとりあえず置いといて、期待通りに動作したら、ポインタとその実体がどう変化するか、それだけを考えて
funcAを作成.確認します。
*x += 3 ;
とあったら、 実際にどんなアセンブリコードになっているか、なんて考えないですよね?それと同様に
funcB(x)
とあったら、funcBの中身を考えずに、funcBの動作だけを考えます。

また、Cとポインタだけで発生することではなく、他の言語でも同じことが起きます。
例えば、Javaのオブジェクトは、メソッドの引数で渡すときには、「参照値」というポインタのような値が使われます。

JavaでmethodA(Object objA) の中で methodB(objA)を実行している
のと
Cで funcA(int * p) の中で funcB(p) を実行している
のとで、参照値/ポインタの扱いはまったく一緒です。



他にも
・Cには、いわゆる「参照渡し」がありません。ポインタ(の値)渡しで代用します。
・Cでは、配列とポインタは密接に関係しています。
例えば、void func(int * a) ; と void func(int a[]) ; は等価です。

この回答への補足

回答ありがとうございます。

>関数にポインタを渡しても、アクセス可能な場所は限られます。
>funcA(&x) としたら、xにアクセスできるのは funcAと、funcAの中で呼ばれる関数だけです。

funcAの中で呼ばれる関数に、そのまま&xを渡したら、内部の関数の、さらのその内部の関数内でポインタ渡しになっていたとき、アクセスは不可能という解釈で良いでしょうか?

補足日時:2013/07/02 23:23
    • good
    • 0
この回答へのお礼

こちらの回答も、ありがとうございます。

お礼日時:2013/07/08 23:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!