blog/content/post/2008/05/02/2008-05-02-『新版c言語プログラミングレッス...

268 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 『新版C言語プログラミングレッスン 入門編』第11章・ポインタ
author: kazu634
date: 2008-05-02
wordtwit_post_info:
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:3971;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- C
- Programming
---
<div class="section">
<p>
 難関に入ります。
</p>
<h4>
「ポインタ」とは何か?
</h4>
<blockquote title="http" cite="http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10">
<p>
「ポインタとは、変数のアドレスをもつ変数である」
</p>
<p>
<cite><a href="http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10', 'http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&#038;s=books&#038;qid=1209639049&#038;sr=1-10:title');" target="_blank">http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10:title</a></cite>
</p>
</blockquote>
<p>
とりあえず研修でハードウェアについてたたき込まれているので、この説明でなんとなくわかる。要は主記憶上のアドレスを格納できる変数を「ポインタ」という…みたいです。
</p>
<p>
<a name="seemore"></a>
</p>
<h4>
「ポインタ」の定義の仕方
</h4>
<p>
 こんな感じだよー。
</p>
<pre class="syntax-highlight">
<span class="synType">int</span> *p;
</pre>
<h4>
「ポインタ」への代入
</h4>
<p>
 「&」演算子を用いると変数のアドレスがわかります。例:
</p>
<pre class="syntax-highlight">
p = &#38;x;
</pre>
<h4>
「ポインタ」の参照
</h4>
<p>
 printfではこんな感じになる。
</p>
<pre class="syntax-highlight">
printf(<span class="synConstant">&#34;</span><span class="synSpecial">%p\n</span><span class="synConstant">&#34;</span>, p);
</pre>
<p>
また、ポインタが指している他の変数の値も参照できる。例えば
</p>
<pre class="syntax-highlight">
<span class="synType">int</span> x;
<span class="synType">int</span> *p;
x = <span class="synConstant">123</span>;
p = &#38;x;
*p = <span class="synConstant">456</span>;
</pre>
<p>
とすると、xの値が456になる。
</p>
<h4>
「ポインタ」のインクリメントとか
</h4>
<blockquote title="http" cite="http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10">
<ul>
<li>
「p++」: ポインタpが「一つ次」の変数を指すようになる
</li>
<li>
「p&#8211;」: ポインタpが「一つ前」の変数を指すようになる
</li>
</ul>
<p>
<cite><a href="http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10', 'http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&#038;s=books&#038;qid=1209639049&#038;sr=1-10:title');" target="_blank">http://www.amazon.co.jp/%E6%96%B0%E7%89%88C%E8%A8%80%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B9%E3%83%B3-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%B5%90%E5%9F%8E%E6%B5%A9/dp/4797336781/ref=sr_1_10?ie=UTF8&s=books&qid=1209639049&sr=1-10:title</a></cite>
</p>
</blockquote>
<h4>
</h4>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;stdio.h&#62;</span>
<span class="synType">void</span> swap_int(<span class="synType">int</span> *xp, <span class="synType">int</span> *yp);
<span class="synType">int</span> main(<span class="synType">void</span>);
<span class="synType">void</span> swap_int(<span class="synType">int</span> *xp, <span class="synType">int</span> *yp)
{
<span class="synType">int</span> tmp;
tmp = *xp;
*xp = *yp;
*yp = tmp;
}
<span class="synType">int</span> main(<span class="synType">void</span>)
{
<span class="synType">int</span> x, y;
x = <span class="synConstant">4</span>;
y = <span class="synConstant">5</span>;
printf (<span class="synConstant">&#34;x = </span><span class="synSpecial">%d</span><span class="synConstant">, y = </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, x, y);
swap_int(&#38;x, &#38;y);
printf (<span class="synConstant">&#34;x = </span><span class="synSpecial">%d</span><span class="synConstant">, y = </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, x, y);
}
</pre>
<p>
ここで個人的に注意すべきなのは、void swap_intのところでの「*xp」などといった表記は、「変数がポインタである」ことを示す。それに対して、以降の「*xp」などは「xpに入っているアドレスが参照している変数」を指す。この違いが分からず、ちょっと混乱してしまった。
</p>
<h4>
配列とポインタの関係
</h4>
<p>
 ポインタのインクリメントは、おそらく配列の内部で使うことを想定しているのだと思われる。
</p>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;stdio.h&#62;</span>
<span class="synType">int</span> main(<span class="synType">void</span>);
<span class="synType">int</span> main(<span class="synType">void</span>)
{
<span class="synType">int</span> x[<span class="synConstant">3</span>] = {<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">9</span>};
<span class="synType">int</span> *p_x;
<span class="synType">int</span> i;
p_x = &#38;x[<span class="synConstant"></span>];
<span class="synStatement">for</span> (i = <span class="synConstant"></span>;i &#60; <span class="synConstant">3</span>;i++) {
*p_x = *p_x * *p_x;
p_x++;
}
<span class="synStatement">for</span> (i = <span class="synConstant"></span>;i &#60; <span class="synConstant">3</span>;i++) {
printf (<span class="synConstant">&#34;x[</span><span class="synSpecial">%d</span><span class="synConstant">]: </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, i, x[i]);
}
<span class="synStatement">return</span>(<span class="synConstant"></span>);
}
</pre>
<p>
これは
</p>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;stdio.h&#62;</span>
<span class="synType">int</span> main(<span class="synType">void</span>);
<span class="synType">int</span> main(<span class="synType">void</span>)
{
<span class="synType">int</span> x[<span class="synConstant">3</span>] = {<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">9</span>};
<span class="synType">int</span> i;
<span class="synStatement">for</span> (i = <span class="synConstant"></span>;i &#60; <span class="synConstant">3</span>;i++) {
x[i] = x[i] * x[i];
}
<span class="synStatement">for</span> (i = <span class="synConstant"></span>;i &#60; <span class="synConstant">3</span>;i++) {
printf (<span class="synConstant">&#34;x[</span><span class="synSpecial">%d</span><span class="synConstant">]: </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, i, x[i]);
}
<span class="synStatement">return</span>(<span class="synConstant"></span>);
}
</pre>
<p>
と結局同じことをしていることになる<span class="footnote"><a href="/sirocco634/#f1" name="fn1" title="でも、私には二つ書き方があることは分かっても、二つの違いは分からなかったりorz。たぶん、効率とかなんかが違うのだと思われる">*1</a></span>
</p>
<h4>
構造体と「ポインタ」の関係
</h4>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;stdio.h&#62;</span>
<span class="synPreProc">#include </span><span class="synConstant">&#60;string.h&#62;</span>
<span class="synType">int</span> main(<span class="synType">void</span>);
<span class="synType">struct</span> student
{
<span class="synType">int</span> id;
<span class="synType">char</span> name[<span class="synConstant">20</span>];
<span class="synType">int</span> japanese;
<span class="synType">int</span> math;
<span class="synType">int</span> eng;
};
<span class="synType">int</span> main(<span class="synType">void</span>)
{
<span class="synType">struct</span> student yukari;
<span class="synType">struct</span> student *p;
yukari.id = <span class="synConstant">1</span>;
strcpy(&#38;yukari.name[<span class="synConstant"></span>], <span class="synConstant">&#34;Yukari&#34;</span>);
yukari.japanese = <span class="synConstant">80</span>;
yukari.math = <span class="synConstant">70</span>;
yukari.eng = <span class="synConstant">100</span>;
p =
<span class="synComment">/* 構造体のポインタを用いた参照はこのように書く */</span>
(*p).id = <span class="synConstant">2</span>;
printf (<span class="synConstant">&#34;Yukari's id: </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, (*p).id);
<span class="synComment">/* もしくはこのように書く */</span>
p-&#62;id = <span class="synConstant">3</span>;
printf (<span class="synConstant">&#34;Yukari's id: </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, p-&#62;id);
<span class="synStatement">return</span>(<span class="synConstant"></span>);
}
</pre>
<h4>
練習問題
</h4>
<p>
 一つ目の変数の阿智が二つ目より小さいときには値を交換し、そうでないときには何もしない関数をポインタを用いて作るよ。
</p>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;stdio.h&#62;</span>
<span class="synType">void</span> swap_bigint(<span class="synType">int</span> *x, <span class="synType">int</span> *y);
<span class="synType">int</span> main(<span class="synType">void</span>);
<span class="synType">void</span> swap_bigint(<span class="synType">int</span> *x, <span class="synType">int</span> *y)
{
<span class="synType">int</span> tmp;
<span class="synStatement">if</span> (*x &#60; *y) {
tmp = *x;
*x = *y;
*y = tmp;
}
}
<span class="synType">int</span> main(<span class="synType">void</span>)
{
<span class="synType">int</span> x, y;
x = <span class="synConstant">5</span>;
y = <span class="synConstant">3</span>;
printf (<span class="synConstant">&#34;Setting Value: x -&#62; </span><span class="synSpecial">%d</span><span class="synConstant">, y -&#62; </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, x, y);
swap_bigint(&#38;x, &#38;y);
printf (<span class="synConstant">&#34;After the swap_value: x -&#62; </span><span class="synSpecial">%d</span><span class="synConstant">, y -&#62; </span><span class="synSpecial">%d\n</span><span class="synConstant">&#34;</span>, x, y);
<span class="synStatement">return</span>(<span class="synConstant"></span>);
}
</pre>
</div>
<div class="footnote">
<p class="footnote">
<a href="/sirocco634/#fn1" name="f1">*1</a>でも、私には二つ書き方があることは分かっても、二つの違いは分からなかったりorz。たぶん、効率とかなんかが違うのだと思われる
</p>
</div>