LoginSignup
3
2

More than 1 year has passed since last update.

【c/c++】constとポインタの関係

Posted at

前置き

constとポインタの関係について調べたので、その記録を残します。

実験などしなくとも、今はネット上でいくらでも解説サイトがあります。

しかしながら今回はあえて実験し、そこから法則性を求めることにした。

実際にコンパイルし、エラーとなる書き方を探る

まず、下記のソースをコンパイルして、どこでエラーが発生するか試す。

source : ptr_cnst.cpp

#include <iostream>
#include <string>

int main()
{
        using std::literals::string_literals::operator""s;

        char str1_1[] = "char[] test1-1.";
        char str2_1[] = "char[] test2-1.";
        char str3_1[] = "char[] test3-1.";
        char str4_1[] = "char[] test4-1.";
        char str5_1[] = "char[] test5-1.";
        char str6_1[] = "char[] test6-1.";
        char str7_1[] = "char[] test7-1.";
        char str8_1[] = "char[] test8-1.";
        char str1_2[] = "char[] test1-2.";
        char str2_2[] = "char[] test2-2.";
        char str3_2[] = "char[] test3-2.";
        char str4_2[] = "char[] test4-2.";
        char str5_2[] = "char[] test5-2.";
        char str6_2[] = "char[] test6-2.";
        char str7_2[] = "char[] test7-2.";
        char str8_2[] = "char[] test8-2.";

        char *p_ch1 = str1_1;
        const char *p_ch2 = str2_1;
        char const*p_ch3 = str3_1;
        char *const p_ch4 = str4_1;
        const char const * p_ch5 = str5_1;
        char const *const p_ch6 = str6_1;
        const char *const p_ch7 = str7_1;
        const char const *const p_ch8 = str8_1;

        p_ch1 = str1_2;
        p_ch2 = str2_2;
        p_ch3 = str3_2;
        p_ch4 = str4_2;
        p_ch5 = str5_2;
        p_ch6 = str6_2;
        p_ch7 = str7_2;
        p_ch8 = str8_2;

        *p_ch1 = '@';
        *p_ch2 = '@';
        *p_ch3 = '@';
        *p_ch4 = '@';
        *p_ch5 = '@';
        *p_ch6 = '@';
        *p_ch7 = '@';
        *p_ch8 = '@';

        std::cout << p_ch1 << std::endl;
        std::cout << p_ch2 << std::endl;
        std::cout << p_ch3 << std::endl;
        std::cout << p_ch4 << std::endl;
        std::cout << p_ch5 << std::endl;
        std::cout << p_ch6 << std::endl;
        std::cout << p_ch7 << std::endl;
        std::cout << p_ch8 << std::endl;
}

下記のコンパイルエラーが発生しました。

$ g++ -std=c++20 -Wall -pedantic-errors ./ptr_cnst.cpp -o ./ptr_cnst.exe
./ptr_cnst.cpp: In function 'int main()':
./ptr_cnst.cpp:29:13: error: duplicate 'const'
   29 |  const char const * p_ch5 = str5_1;
      |             ^~~~~
      |             -----
./ptr_cnst.cpp:32:13: error: duplicate 'const'
   32 |  const char const *const p_ch8 = str8_1;
      |             ^~~~~
      |             -----
./ptr_cnst.cpp:37:8: error: assignment of read-only variable 'p_ch4'
   37 |  p_ch4 = str4_2; // error: assignment of read-only variable 'p_ch4'
      |  ~~~~~~^~~~~~~~
./ptr_cnst.cpp:39:8: error: assignment of read-only variable 'p_ch6'
   39 |  p_ch6 = str6_2;
      |  ~~~~~~^~~~~~~~
./ptr_cnst.cpp:40:8: error: assignment of read-only variable 'p_ch7'
   40 |  p_ch7 = str7_2;
      |  ~~~~~~^~~~~~~~
./ptr_cnst.cpp:41:8: error: assignment of read-only variable 'p_ch8'
   41 |  p_ch8 = str8_2;
      |  ~~~~~~^~~~~~~~
./ptr_cnst.cpp:44:9: error: assignment of read-only location '* p_ch2'
   44 |  *p_ch2 = '@'; // error: assignment of read-only location '* p_ch2'
      |  ~~~~~~~^~~~~
./ptr_cnst.cpp:45:9: error: assignment of read-only location '* p_ch3'
   45 |  *p_ch3 = '@'; // error: assignment of read-only location '* p_ch3'
      |  ~~~~~~~^~~~~
./ptr_cnst.cpp:47:9: error: assignment of read-only location '* p_ch5'
   47 |  *p_ch5 = '@';
      |  ~~~~~~~^~~~~
./ptr_cnst.cpp:48:9: error: assignment of read-only location '*(const char*)p_ch6'
   48 |  *p_ch6 = '@';
      |  ~~~~~~~^~~~~
./ptr_cnst.cpp:49:9: error: assignment of read-only location '*(const char*)p_ch7'
   49 |  *p_ch7 = '@';
      |  ~~~~~~~^~~~~
./ptr_cnst.cpp:50:9: error: assignment of read-only location '*(const char*)p_ch8'
   50 |  *p_ch8 = '@';
      |  ~~~~~~~^~~~~

エラー箇所をコメントアウトし、コンパイルを通す

下記のようにエラー行をコメントアウトするとコンパイルが通った。

source : ptr_cnst.cpp

#include <iostream>
#include <string>

int main()
{
        using std::literals::string_literals::operator""s;

        char str1_1[] = "char[] test1-1.";
        char str2_1[] = "char[] test2-1.";
        char str3_1[] = "char[] test3-1.";
        char str4_1[] = "char[] test4-1.";
//      char str5_1[] = "char[] test5-1.";
        char str6_1[] = "char[] test6-1.";
        char str7_1[] = "char[] test7-1.";
//      char str8_1[] = "char[] test8-1.";
        char str1_2[] = "char[] test1-2.";
        char str2_2[] = "char[] test2-2.";
        char str3_2[] = "char[] test3-2.";
        char str4_2[] = "char[] test4-2.";
//      char str5_2[] = "char[] test5-2.";
        char str6_2[] = "char[] test6-2.";
        char str7_2[] = "char[] test7-2.";
//      char str8_2[] = "char[] test8-2.";

        char *p_ch1 = str1_1;
        const char *p_ch2 = str2_1;
        char const*p_ch3 = str3_1;
        char *const p_ch4 = str4_1;
//      const char const * p_ch5 = str5_1;      // error: duplicate 'const'
        char const *const p_ch6 = str6_1;
        const char *const p_ch7 = str7_1;
//      const char const *const p_ch8 = str8_1; // error: duplicate 'const'

        p_ch1 = str1_2;
        p_ch2 = str2_2;
        p_ch3 = str3_2;
//      p_ch4 = str4_2; // error: assignment of read-only variable 'p_ch4'
//      p_ch5 = str5_2;
//      p_ch6 = str6_2; // error: assignment of read-only variable 'p_ch6'
//      p_ch7 = str7_2; // error: assignment of read-only variable 'p_ch7'
//      p_ch8 = str8_2;

        *p_ch1 = '@';
//      *p_ch2 = '@';   // error: assignment of read-only location '* p_ch2'
//      *p_ch3 = '@';   // error: assignment of read-only location '* p_ch3'
        *p_ch4 = '@';
//      *p_ch5 = '@';
//      *p_ch6 = '@';   // error: assignment of read-only location '*(const char*)p_ch6'
//      *p_ch7 = '@';   // error: assignment of read-only location '*(const char*)p_ch7'
//      *p_ch8 = '@';

        std::cout << p_ch1 << std::endl;
        std::cout << p_ch2 << std::endl;
        std::cout << p_ch3 << std::endl;
        std::cout << p_ch4 << std::endl;
//      std::cout << p_ch5 << std::endl;
        std::cout << p_ch6 << std::endl;
        std::cout << p_ch7 << std::endl;
//      std::cout << p_ch8 << std::endl;
}

実行結果:

$ g++ -std=c++20 -Wall -pedantic-errors ./ptr_cnst.cpp -o ./ptr_cnst.exe
./ptr_cnst.cpp: In function 'int main()':
./ptr_cnst.cpp:19:7: warning: unused variable 'str4_2' [-Wunused-variable]
   19 |  char str4_2[] = "char[] test4-2.";
      |       ^~~~~~
./ptr_cnst.cpp:21:7: warning: unused variable 'str6_2' [-Wunused-variable]
   21 |  char str6_2[] = "char[] test6-2.";
      |       ^~~~~~
./ptr_cnst.cpp:22:7: warning: unused variable 'str7_2' [-Wunused-variable]
   22 |  char str7_2[] = "char[] test7-2.";
      |       ^~~~~~

$ ./ptr_cnst.exe
@har[] test1-2.
char[] test2-2.
char[] test3-2.
@har[] test4-1.
char[] test6-1.
char[] test7-1.

実行結果まとめ

先ほどの実行結果を表にまとめると下記のようになる。

constの付け方 変数の定義 ポインタの指す先
("アドレス")を変更
ポインタの指す先の
"値"を変更
char *p_ch1 可能 可能 可能
const char *p_ch2 可能 可能 不可能
char const*p_ch3 可能 可能 不可能
char *const p_ch4 可能 不可能 可能
const char const * p_ch5 不可能
char const *const p_ch6 可能 不可能 不可能
const char *const p_ch7 可能 不可能 不可能
const char const *const p_ch8 不可能

constとポインタの関係【結論】

constの位置 動作
*の前 ポインタの指す先の"値"の変更が不可
*の後 ポインタの指す先("アドレス")の変更が不可

つまりconstが*の後にあるか、前にあるかで動作が変わるということである。

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2