ページ 11

文字配列のswap関数とマクロ関数

Posted: 2016年9月25日(日) 17:06
by Ohagi
文字配列のswap関数とポインタの関係がわかりません。

コード:

#define swap(type, x, y) do { type t = x; x = y; y = t; } while (0)
参考書では上のようなスワップ関数が紹介されていましたが
これをマクロ関数ではなく普通の関数として書くとうまくスワップされません。

コード:

#include <stdio.h>

void swap(char *s1, char *s2)
{
  char *t = s1;
  s1 = s2;
  s2 = t;
}

int main(void)
{
  char *str[2] = {"windows", "linux"};
  swap(str[0], str[1]);
  return 0;
}


これにアドレス演算子を足してみると問題なくスワップされるのですがよくわかりません。

コード:

#include <stdio.h>

void swap(char **s1, char **s2)
{
  char *t = *s1;
  *s1 = *s2;
  *s2 = t;
}

int main(void)
{
  char *str[2] = {"book", "helm"};

  swap(&str[0], &str[1]);
  
  return 0;
}

1.
マクロ関数をそのまま?書き写した関数の挙動が違う理由

2.
コード3のswap(&str[0], &str[1]);は画像でいうbの値をスワップしていますよね?
ではコード2のswap(str[0], str[1])はどこの値をスワップしているのでしょうか? a?
画像のaをスワップしても結果的にはスワップされていそうな気がするのですがわかりません...

画像

Re: 文字配列のswap関数とマクロ関数

Posted: 2016年9月25日(日) 22:41
by box
kazuki2655 さんが書きました: これにアドレス演算子を足してみると問題なくスワップされるのですがよくわかりません。
入れ替えた後の結果を出力していないので、本当に問題ないのかどうかよくわかりません。

Re: 文字配列のswap関数とマクロ関数

Posted: 2016年9月26日(月) 01:20
by みけCAT
kazuki2655 さんが書きました:1.
マクロ関数をそのまま?書き写した関数の挙動が違う理由
マクロは文字列(正確にはトークン列)の「コピペと引数の置換」で書かれた場所に「展開」されるが、
関数は(少なくともソースコードレベルでは)「展開」のようなことは起こらず、呼び出し元とは分離されたスコープを持つためです。
kazuki2655 さんが書きました:2.
コード3のswap(&str[0], &str[1]);は画像でいうbの値をスワップしていますよね?
ではコード2のswap(str[0], str[1])はどこの値をスワップしているのでしょうか? a?
呼び出し元からコピーされた仮引数s1とs2の値をスワップしています。
コピーの値を変更しても、コピー元のstrの要素への影響はありません。

Re: 文字配列のswap関数とマクロ関数

Posted: 2016年9月26日(月) 01:23
by みけCAT
オフトピック
box さんが書きました:
kazuki2655 さんが書きました: これにアドレス演算子を足してみると問題なくスワップされるのですがよくわかりません。
入れ替えた後の結果を出力していないので、本当に問題ないのかどうかよくわかりません。
問題ないのかどうかを知りたいなら、入れ替えた後の結果を出力すればいいでしょう。
例えば、デバッガを用いて出力させる方法が考えられます。

Re: 文字配列のswap関数とマクロ関数

Posted: 2016年9月26日(月) 01:58
by Ohagi
マクロは文字列(正確にはトークン列)の「コピペと引数の置換」で書かれた場所に「展開」されるが、
関数は(少なくともソースコードレベルでは)「展開」のようなことは起こらず、呼び出し元とは分離されたスコープを持つためです。
マクロの基本的な部分が頭から抜けていました。
ありがとうございます。
呼び出し元からコピーされた仮引数s1とs2の値をスワップしています。
コピーの値を変更しても、コピー元のstrの要素への影響はありません。
配列の先頭文字を渡して仮引数でシャッフルしていただけだったのですね。
改めて指摘を受けてわかったような気がします。
ありがとうございました。

Re: 文字配列のswap関数とマクロ関数

Posted: 2016年9月26日(月) 05:55
by box
みけCAT さんが書きました: 問題ないのかどうかを知りたいなら、入れ替えた後の結果を出力すればいいでしょう。
まさにそこ!デバッガーなんて七面倒くさい手段を使わずとも、入れ替えた直後にprintfするか何かして、
問題があるのかないのかなんで確認してないんだろう?って思ったしだいです。
ふつうしますよね?