[关闭]
@Wayne-Z 2017-10-19T03:38:31.000000Z 字数 5368 阅读 1335

A Deeper Look at Const

ssd6



Questions

  1. const int a;
  2. int const a;
  3. const int *a;
  4. int *const a;
  5. int const *a const;

What does them means?

Analysis

Firstly, we should know that the order in which the declaration specifiers appear in declaration does not matter. So for the first two declaration:

  1. const int a;
  2. int const a;

They are equivalent. They both means that a is a constant integer, whose value can not be changed.

However, since pointer declarations read from right-to-left, and T const and volatile are the only declaration specifiers that can also appear in declarators. So for these two declarations,

  1. const int *a;
  2. int const *a;

they are equivalent, they both means a is pointer to constant integer. The value it points can not be modified, but its own value can be changed, it can points to another constant integer as we like.

In the contrast, for the next line

  1. int *const a;

we can know it means that a is constant pointer to an integer. Its value can not change, but we can change the value of integer it points.

When it comes to

  1. int const *a const;

Both the pointer and the value to which it points are constant.

Test

It can be tested whether a is avaliable for change, let's try to see what will happen in the following code.

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. int i = 5;
  5. int a = 10;
  6. const int ci=15;
  7. int const ic = 20;
  8. const int *cip = &ci;
  9. int const *icp = &ic;
  10. int *const ipc = &i;
  11. int const* icpc const = &ci;
  12. cout <<"int i: < "<< &i << " > "<< i <<endl;
  13. cout <<"const int ci: < "<< &ci << " > "<< ci <<endl;
  14. cout <<"int const ic: < "<< &ic << " > "<< ic<< endl;
  15. cout <<"const int *cip = &ci; so cip: < "<< cip << " > "<< *cip <<endl;
  16. cout <<"int const *icp = &ic; so icp: < "<< icp << " > "<< *icp<< endl;
  17. cout <<"int *const ipc = &i; so ipc: < "<< ipc << " > "<< *ipc<< endl;
  18. cout <<"int const* icpc const = &ci; so icpc: < "<< icpc << " > "<< *icpc<< endl;
  19. cout <<"icpc: < "<<icpc << " > "<< *icpc<< endl;
  20. ci = i;// not avaliable
  21. ic = i;// not avaliable
  22. ipc = &ic;// not avaliable
  23. ipc = &a;// not avaliable
  24. cip = &i;
  25. icp = &i;
  26. ipc = &ic;//not avaliable
  27. icpc = &ic;
  28. cout <<"After operation cip = &i; cip: < "<< cip << " > "<< *cip <<endl;
  29. cout <<"After operation icp = &i; icp: < "<< icp << " > "<< *icp<< endl;
  30. cout <<"The value of icp and cip is changable, ipc can not be modified."<< endl;
  31. *cip = ci;// not avaliable
  32. *icp = ci;// not avaliable
  33. i = ci;
  34. *ipc = ci;
  35. *icpc = ic;
  36. cout <<"After *ipc = ci; ipc < "<< ipc << " > "<< *ipc <<endl;
  37. cout <<"After i=ci; cip: < "<< cip << " > "<< *cip <<endl;
  38. cout <<"After i=ci; icp: < "<< icp << " > "<< *icp <<endl;
  39. cout <<"The integer that icp, cip and ipc point to can be changed, but *cip and *icp can not be modified directly!"<< endl;
  40. return 0;
  41. }

After compilation, we can see these errors:

  1. test.cpp: In function 'int main()':
  2. test.cpp:11:18: error: expected initializer before 'const'
  3. test.cpp:19:55: error: 'icpc' was not declared in this scope
  4. test.cpp:21:7: error: assignment of read-only variable 'ci'
  5. test.cpp:22:7: error: assignment of read-only variable 'ic'
  6. test.cpp:23:9: error: assignment of read-only variable 'ipc'
  7. test.cpp:23:9: error: invalid conversion from 'const int*' to 'int*' [-fpermissive]
  8. test.cpp:24:9: error: assignment of read-only variable 'ipc'
  9. test.cpp:27:9: error: assignment of read-only variable 'ipc'
  10. test.cpp:27:9: error: invalid conversion from 'const int*' to 'int*' [-fpermissive]
  11. test.cpp:32:9: error: assignment of read-only location '* cip'
  12. test.cpp:33:9: error: assignment of read-only location '* icp'

The outcome is funny, first we know that the declaration int const* icpc const = &ci; is not accepted, and those declarations right commented not avaliable is indeed not avaliable. So we try again, change int const* icpc const = &ci; to int const* const icpc = &ci; and comments those unavaliable declarations like the following. We still got an error:

  1. test.cpp: In function 'int main()':
  2. test.cpp:28:10: error: assignment of read-only variable 'icpc'

Actually I have to say I have never seen this kind declaration used in any code, so comment it as well, we got:

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. int i = 5;
  5. //int a = 10;
  6. const int ci=15;
  7. int const ic = 20;
  8. const int *cip = &ci;
  9. int const *icp = &ic;
  10. int *const ipc = &i;
  11. //int const* const icpc = &i;
  12. cout <<"int i: < "<< &i << " > "<< i <<endl;
  13. cout <<"const int ci: < "<< &ci << " > "<< ci <<endl;
  14. cout <<"int const ic: < "<< &ic << " > "<< ic<< endl;
  15. cout <<"const int *cip = &ci; so cip: < "<< cip << " > "<< *cip <<endl;
  16. cout <<"int const *icp = &ic; so icp: < "<< icp << " > "<< *icp<< endl;
  17. cout <<"int *const ipc = &i; so ipc: < "<< ipc << " > "<< *ipc<< endl;
  18. //cout <<"int const* icpc const = &ci; so icpc: < "<< icpc << " > "<< *icpc<< endl;
  19. //cout <<"icpc: < "<<icpc << " > "<< *icpc<< endl;
  20. //ci = i;// not avaliable
  21. //ic = i;// not avaliable
  22. //ipc = &ic;// not avaliable
  23. //ipc = &a;// not avaliable
  24. cip = &i;
  25. icp = &i;
  26. //ipc = &ic;//not avaliable
  27. //icpc = &ic;
  28. cout <<"After operation cip = &i; cip: < "<< cip << " > "<< *cip <<endl;
  29. cout <<"After operation icp = &i; icp: < "<< icp << " > "<< *icp<< endl;
  30. cout <<"The value of icp and cip is changable, ipc can not be modified."<< endl;
  31. //*cip = ci;// not avaliable
  32. //*icp = ci;// not avaliable
  33. i = ci;
  34. *ipc = ci;
  35. //*icpc = ic;
  36. cout <<"After *ipc = ci; ipc < "<< ipc << " > "<< *ipc <<endl;
  37. cout <<"After i=ci; cip: < "<< cip << " > "<< *cip <<endl;
  38. cout <<"After i=ci; icp: < "<< icp << " > "<< *icp <<endl;
  39. cout <<"The integer that icp, cip and ipc point to can be changed, but *cip and *icp can not be modified directly!"<< endl;
  40. return 0;
  41. }

Outcome

The code above passes the compilation, then we run it, we can see the outcomes like the following:

  1. int i: < 0x64fd64 > 5
  2. const int ci: < 0x64fd60 > 15
  3. int const ic: < 0x64fd5c > 20
  4. const int *cip = &ci; so cip: < 0x64fd60 > 15
  5. int const *icp = &ic; so icp: < 0x64fd5c > 20
  6. int *const ipc = &i; so ipc: < 0x64fd64 > 5
  7. After operation cip = &i; cip: < 0x64fd64 > 5
  8. After operation icp = &i; icp: < 0x64fd64 > 5
  9. The value of icp and cip is changable, ipc can not be modified.
  10. After *ipc = ci; ipc < 0x64fd64 > 15
  11. After i=ci; cip: < 0x64fd64 > 15
  12. After i=ci; icp: < 0x64fd64 > 15
  13. The integer that icp, cip and ipc point to can be changed, but *cip and *icp can not be modified directly!

Conclusion

The test outcomes proved our analysis, and we can know that we still can modifier the value that const int *p and int const *p point to indirectly. Also, it maybe different in other GCC version ,since my version is just 4.7.

Reference

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注