指向指针的常量指针...

引言


最近,他们向我提出了一个问题:“它是什么以及如何使用它?”,显示以下代码:

extern "C" { void byteMaskDowngrade(byte***const byteMask, const byte *const *const && source) { // - . } //  . } 

这位同事是我的工作同事,我们并没有立即理解函数声明中参数的确切含义(对于那些需要在声明中声明此类信息的人:密码学)。

考虑到研讨会上同事可能存在的问题,我决定创建这篇文章,作为备忘单,即以下两个问题的答案:

  1. 如何在这里写这样的广告?
  2. 以及如何正确阅读它们?

“ *”


带星号的情况是最常见的情况,但是,在这里也可能引起误解:

  • 如何:

    • 因此:

       const byte p; 
    • 大概:

       byte const p; 

  • 或在输入“ *”的情况下:

    • 因此:

       byte *const p; 
    • 大概:

       const byte *p; 

严格来说,从编译器的角度来看,星号的存在及其在表达式中的位置构成了一个边缘问题,因为 条目的最终含义将有所不同。 在上述情况下,const说明符的存在在考虑其相对于数据类型的位置时没有任何区别,但是,当出现指针时,情况发生了巨大变化:1、2、3 ...好了,您了解:

 void p() { //   . byte * a = new byte{1}; a++; // . a[0]++; // . //    . const byte * b = new byte{1}; b++; // . //b[0]++; // . //    . byte *const c = new byte{1}; //c++; // . c[0]++; // . //     . const byte *const d = new byte{1}; //d++; // . //d[0]++; // . } 

当第二个指针出现时,所有这些看起来都比较有趣(这里已经开始跟踪一种有效的写入读取规则):

 void pp() { //     . byte ** a = new byte * { new byte{1} }; a++; // . a[0]++; // . a[0][0]++; // . //      . const byte ** b = new const byte * { new byte{1}}; b++; // . b[0]++; // . //b[0][0]++; // . //      . byte *const * c = new byte * { new byte{1}}; c++; // . //c[0]++; // . c[0][0]++; // . //      . byte * *const d = new byte * { new byte{1}}; //d++; // . d[0]++; // . d[0][0]++; // . //       . const byte *const * e = new const byte *const { new byte{1}}; e++; // . //e[0]++; // . //e[0][0]++; // . //       . const byte * *const f = new const byte * { new byte{1}}; //f++; // . f[0]++; // . //f[0][0]++; // . //       . byte *const *const g = new byte *const { new byte{1}}; //g++; // . //g[0]++; // . g[0][0]++; // . //        . const byte *const *const h = new const byte *const { new byte{1}}; //h++; // . //h[0]++; // . //h[0][0]++; // . } 

如您所见,双指针可以用多达8种不同的方式表示,每种方式都定义了一种使用目标数据的特殊方式。

读取此类表达式的规则如下:

  • 在表达式中查找“ =”符号,然后从右到左读取表达式;
  • 跳过变量名;
  • 进一步的会议“ *”(表示常规指针)或“ * const”(常量指针);
  • 因此我们读取直到遇到数据类型(字节);
  • 数据类型左侧的最后一个字可以是const,它的存在意味着整个结构都引用了无法更改的数据; 如果const不是,则有可能。

这种写作和阅读形式甚至使最复杂的表达也易于阅读和理解。

这是带有三重指针的一组完整表达式的示例:

“ ***”


 void ppp() { //       . byte *** a = new byte * * { new byte * {new byte{1}} }; a++; // . a[0]++; // . a[0][0]++; // . a[0][0][0]++; // . //        . const byte *** b = new const byte * * { new const byte * {new byte{1}} }; b++; // . b[0]++; // . b[0][0]++; // . //b[0][0][0]++; // . //        . byte*const * * c = new byte *const * { new byte *const {new byte{1}} }; c++; // . c[0]++; // . //c[0][0]++; // . c[0][0][0]++; // . //        . byte * *const * d = new byte * *const { new byte * {new byte{1}} }; d++; // . //d[0]++; // . d[0][0]++; // . d[0][0][0]++; // . //        . byte *** const e = new byte * * { new byte * {new byte{1}} }; //e++; // . e[0]++; // . e[0][0]++; // . e[0][0][0]++; // . //         . const byte *const * * f = new const byte *const * { new const byte *const {new byte{1}} }; f++; // . f[0]++; // . //f[0][0]++; // . //f[0][0][0]++; // . //         . const byte * *const * g = new const byte * *const{ new const byte * {new byte{1}} }; g++; // . //g[0]++; // . g[0][0]++; // . //g[0][0][0]++; // . //         . const byte * * *const h = new const byte * *{ new const byte * {new byte{1}}}; //h++; // . h[0]++; // . h[0][0]++; // . //h[0][0][0]++; // . //         . byte *const * *const i = new byte *const * { new byte *const {new byte{1}}}; //i++; // . i[0]++; // . //i[0][0]++; // . i[0][0][0]++; // . //         . byte * *const *const j = new byte * *const { new byte * {new byte{1}}}; //j++; // . //j[0]++; // . j[0][0]++; // . j[0][0][0]++; // . //         . byte *const *const * k = new byte *const *const {new byte *const{new byte{1}}}; k++; // . //k[0]++; // . //k[0][0]++; // . k[0][0][0]++; // . //           const //           . const byte *const *const *const m = new const byte *const *const {new const byte *const {new byte{1}}}; //m++; // . //m[0]++; // . //m[0][0]++; // . //m[0][0][0]++; // . } 

Source: https://habr.com/ru/post/zh-CN468605/


All Articles