为什么在C ++中使用“*(*(array + i)+ j)”而不是“array [i] [j]”?

时间:2017-02-04 04:07:44

标签: c++ pointers

在什么样的情况下,我应该使用它的棘手形式?它会生成更快的二进制代码吗?如果我可以使用[] []表示法来完成这项工作,我是否还应该为某些原因付出额外的努力并用指针实现它? 对于单个数据,我理解指针的需要。我要求专门针对二维数组,而不是关于使用指针的一般意义。

4 个答案:

答案 0 :(得分:5)

  

在什么样的情况下,我应该使用它的棘手形式?

从不,除非您参加@M.M' comment

中提到的代码混淆竞赛
  

它是否会生成更快的二进制代码?

不,发出的汇编指令应与任何体面的编译器相同。

  

我是否还应该出于某种原因付出额外的努力并用指针实现它?

没有。请改用标准容器或智能指针。不要使用原始的c风格数组和指针。

对于已知尺寸,最简单的方法是

std::array<std::array<T,5>,10> array2D;

对于尺寸变化的2D阵列,您可以使用

size_t rows, columns;
std::cout << "Enter row and column size please > " << std::flush;
if(std::cin >> rows >> columns) {
    std::vector<std::vector<T>> array2D(rows,std::vector<T>(columns));
}

要优化2D数组以使用连续的动态内存块,请考虑编写一个小的包装类,将行和列偏移转换为内部值位置(例如,保持在简单的std::vector中)。

答案 1 :(得分:1)

除了@πάνταῥεῖ的建议之外,最好编写C ++表达式,这样类似的类型可以代替变量 - 泛型代码的原理。

std::array是C数组的首选替代品。 (二维情况看起来像std::array< std::array< int, M >, N >。)它不支持+运算符,因此混淆的表达式会阻碍向它的迁移,或任何其他类似容器的类型,例如{{1 }}

答案 2 :(得分:0)

通常没有理由比EXCEPTION: Response with status: 0 for URL: null表单更喜欢*(array + i)表单。同样,没有理由更喜欢array[i]表单而不是*(*(array + i) + j)

在语义上它们是等价的,并且编译器能够发出更有效的“二进制代码” - 在两种情况下通常都是相同的。

实际上,人类通常会更容易理解array[i][j]形式,因此除非您试图混淆人们(例如混淆),否则这样做更为可取。

在使用其他形式的指针算法时,了解等价性至关重要。这样可以更有效地选择技术。 C ++标准库支持迭代器(一种通用形式的指针)来处理范围并不是偶然的,并且通常鼓励使用它们而不是简单的array[i][j]语法。

答案 3 :(得分:0)

当您解释2d数组如何工作时。如果数组是多维的,那个表达式就是使用数组名称可能出错的反例。让我们说,这不是一个罕见的错误。许多缺乏经验的程序员所做的事情:

int arr[10][20];

for (int I =0; I<200; I+=1) *(arr + I) = <some value based on I>;

在最佳情况下,他们会遇到&#34;无法转换为&#39; int&#39; to&#39; int [20]&#34;错误并转到他们更好的(或SO网站)。在最糟糕的情况下,他们变得聪明了#34;并使用type-cast来欺骗编译器。

他们知道单维数组是如何工作的,因为它存在于K&amp; R以后的每本书中,并且一旦我变得大于9,他们就不会意识到它们会超出数组。表达式< / p>

*(*(arr + i) + j)

表明数组的索引相对于数组名称降级的指针是可乘的。更多&#34;适当&#34;做他们想做的事情的方法是使用指针int:

int  *p = (int *)&arr[0][0];

for (int I = 0; I < 200; I++) 
    *(p+I) = <some value based on I;

但严格地说,除非你使用指向unsigned char的指针,否则C ++标准也不能保证这一点。

unsigned char *p = (unsigned char*)&arr[0][0];

for (int I = 0; I < 200; I++) 
    *(int*)(p + I*sizeof(int)) = I;

在这里仍然必须小心,如果平台假设填充,并且数组的元素实际上是需要在末尾填充的类型(例如结构)。

如果我们输出结果数组:

cout << "arr[][] = { ";
 for (int i = 0; i < 10; i++) 
 {
     cout << "\n{";
     for (int j = 0; j < 20; j++) 
         cout << arr[i][j]<< " ";
     cout << "}";
 }
 cout << "}\n";

我们得到:

arr[][] = { 
{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 }
{20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 }
{40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 }
{60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 }
{80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 }
{100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 }
{120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 }
{140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 }
{160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 }
{180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 }}