268 lines
13 KiB
Markdown
268 lines
13 KiB
Markdown
|
---
|
|||
|
title: 『新版C言語プログラミングレッスン 入門編』第11章・ポインタ
|
|||
|
author: kazu634
|
|||
|
date: 2008-05-02
|
|||
|
url: /2008/05/02/_971/
|
|||
|
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&s=books&qid=1209639049&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 = &x;
|
|||
|
</pre>
|
|||
|
|
|||
|
<h4>
|
|||
|
「ポインタ」の参照
|
|||
|
</h4>
|
|||
|
|
|||
|
<p>
|
|||
|
printfではこんな感じになる。
|
|||
|
</p>
|
|||
|
|
|||
|
<pre class="syntax-highlight">
|
|||
|
printf(<span class="synConstant">"</span><span class="synSpecial">%p\n</span><span class="synConstant">"</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 = &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–」: ポインタ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&s=books&qid=1209639049&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"><stdio.h></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">"x = </span><span class="synSpecial">%d</span><span class="synConstant">, y = </span><span class="synSpecial">%d\n</span><span class="synConstant">"</span>, x, y);
|
|||
|
swap_int(&x, &y);
|
|||
|
printf (<span class="synConstant">"x = </span><span class="synSpecial">%d</span><span class="synConstant">, y = </span><span class="synSpecial">%d\n</span><span class="synConstant">"</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"><stdio.h></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 = &x[<span class="synConstant"></span>];
|
|||
|
<span class="synStatement">for</span> (i = <span class="synConstant"></span>;i < <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 < <span class="synConstant">3</span>;i++) {
|
|||
|
printf (<span class="synConstant">"x[</span><span class="synSpecial">%d</span><span class="synConstant">]: </span><span class="synSpecial">%d\n</span><span class="synConstant">"</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"><stdio.h></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 < <span class="synConstant">3</span>;i++) {
|
|||
|
x[i] = x[i] * x[i];
|
|||
|
}
|
|||
|
<span class="synStatement">for</span> (i = <span class="synConstant"></span>;i < <span class="synConstant">3</span>;i++) {
|
|||
|
printf (<span class="synConstant">"x[</span><span class="synSpecial">%d</span><span class="synConstant">]: </span><span class="synSpecial">%d\n</span><span class="synConstant">"</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"><stdio.h></span>
|
|||
|
<span class="synPreProc">#include </span><span class="synConstant"><string.h></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(&yukari.name[<span class="synConstant"></span>], <span class="synConstant">"Yukari"</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">"Yukari's id: </span><span class="synSpecial">%d\n</span><span class="synConstant">"</span>, (*p).id);
|
|||
|
<span class="synComment">/* もしくはこのように書く */</span>
|
|||
|
p->id = <span class="synConstant">3</span>;
|
|||
|
printf (<span class="synConstant">"Yukari's id: </span><span class="synSpecial">%d\n</span><span class="synConstant">"</span>, p->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"><stdio.h></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 < *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">"Setting Value: x -> </span><span class="synSpecial">%d</span><span class="synConstant">, y -> </span><span class="synSpecial">%d\n</span><span class="synConstant">"</span>, x, y);
|
|||
|
swap_bigint(&x, &y);
|
|||
|
printf (<span class="synConstant">"After the swap_value: x -> </span><span class="synSpecial">%d</span><span class="synConstant">, y -> </span><span class="synSpecial">%d\n</span><span class="synConstant">"</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>
|