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

268 lines
13 KiB
Markdown
Raw Normal View History

2019-03-31 11:00:21 +00:00
---
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>