float arrayName[][] 和 float (* arrayNamePointer)[] 有什么区别
what's the difference between float arrayName[][] and float (* arrayNamePointer)[]
下面发生了什么?
以下是 C Primer Plus 的节选:
const float rain[YEARS][MONTHS] =
{
{ 4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6 },
{ 8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3 },
{ 9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4 },
{ 7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2 },
{ 7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2 }
};
int year, month;
float subtot, total;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YEARS; year++)
{
// for each year, sum rainfall for each month
for (month = 0, subtot = 0; month < MONTHS; month++)
{
subtot += rain[year][month];
}
printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot; // total for all years
}
我不得不将其更改为使用指针而不是数组下标。
所以我选择了:
[....]
float (* rainPointer)[2];
rainPointer = rain;
[....]
subtot += *(*(rainPointer + year) + month);
这适用于第 0 年。年份正确递增,月份正确重置。但是,第 1 年并没有指向我期望的位置。我已经经历了一百万次,我 运行 他们并排,rainPointer 总是(在我看来)似乎是正确的,年份和月份总是正确的。
我通过 google 找到了答案,我应该使用:
subtot += *(*(rain + year) + month);
rain 和 rainPointer 有什么区别?如果它们都指向两个整数数组的开头,为什么它们不一样?
发生了一些我显然没有意识到或完全不知道的事情。
rain 是一个声明为 like
的二维数组
const float rain[YEARS][MONTHS];
在表达式中,数组的名称被转换为指向数组第一个元素的指针。例如,如果你有一个数组
T rain[YEARS];
然后在表达式中 rain
被转换为 T *
类型的指针
其实一个二维数组就是一个一维数组,其中的元素又是一维数组。
因此声明
const float rain[YEARS][MONTHS];
可以这样写
typedef float T[MONTHS];
const T rain[YEARS];
其中 T 的类型为 float [MONTHS}
因此 rain
被转换为指向其第一个元素的指针,即指向其第一行的指针,然后由于指针算术表达式 rain + year
是指向一维数组的指针(行)对应于今年。
表达式 *(rain + year) 产生这个数组就是这一行。
所以 *(rain + year) 是一维数组中的某行。再次将数组转换为指向其第一个元素的指针。元素的类型是 const float
因此表达式 *(rain + year) + month
是指向此一维数组(行)中对应于给定月份的元素的指针。
最后表达式 *(*(rain + year) + month)
产生了该行的这个元素。
因此使用表达式 rain + year
可以遍历行。使用表达式 *(rain + year) + month
遍历给定行的元素
.
如果你只想使用指针重写循环,那么它们可以看起来像
const float ( *rain_ptr )[MONTHS];
const float *month_ptr;
float total = 0.0f;
for ( rain_ptr = rain; rain_ptr != rain + YEARS; ++rain_ptr )
{
// for each year, sum rainfall for each month
float subtot = 0.0f;
for ( month_ptr = *rain_ptr; month_ptr != *rain_ptr + MONTHS; ++month_ptr )
{
subtot += *month_ptr;
}
printf("%5d %15.1f\n", 2010 + rain_ptr - rain, subtot);
total += subtot; // total for all years
}
当然,如果编译器允许,则无需在循环之前声明指针。最好在循环语句中声明它们。
下面发生了什么?
以下是 C Primer Plus 的节选:
const float rain[YEARS][MONTHS] =
{
{ 4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6 },
{ 8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3 },
{ 9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4 },
{ 7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2 },
{ 7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2 }
};
int year, month;
float subtot, total;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YEARS; year++)
{
// for each year, sum rainfall for each month
for (month = 0, subtot = 0; month < MONTHS; month++)
{
subtot += rain[year][month];
}
printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot; // total for all years
}
我不得不将其更改为使用指针而不是数组下标。
所以我选择了:
[....]
float (* rainPointer)[2];
rainPointer = rain;
[....]
subtot += *(*(rainPointer + year) + month);
这适用于第 0 年。年份正确递增,月份正确重置。但是,第 1 年并没有指向我期望的位置。我已经经历了一百万次,我 运行 他们并排,rainPointer 总是(在我看来)似乎是正确的,年份和月份总是正确的。
我通过 google 找到了答案,我应该使用:
subtot += *(*(rain + year) + month);
rain 和 rainPointer 有什么区别?如果它们都指向两个整数数组的开头,为什么它们不一样?
发生了一些我显然没有意识到或完全不知道的事情。
rain 是一个声明为 like
的二维数组const float rain[YEARS][MONTHS];
在表达式中,数组的名称被转换为指向数组第一个元素的指针。例如,如果你有一个数组
T rain[YEARS];
然后在表达式中 rain
被转换为 T *
其实一个二维数组就是一个一维数组,其中的元素又是一维数组。
因此声明
const float rain[YEARS][MONTHS];
可以这样写
typedef float T[MONTHS];
const T rain[YEARS];
其中 T 的类型为 float [MONTHS}
因此 rain
被转换为指向其第一个元素的指针,即指向其第一行的指针,然后由于指针算术表达式 rain + year
是指向一维数组的指针(行)对应于今年。
表达式 *(rain + year) 产生这个数组就是这一行。
所以 *(rain + year) 是一维数组中的某行。再次将数组转换为指向其第一个元素的指针。元素的类型是 const float
因此表达式 *(rain + year) + month
是指向此一维数组(行)中对应于给定月份的元素的指针。
最后表达式 *(*(rain + year) + month)
产生了该行的这个元素。
因此使用表达式 rain + year
可以遍历行。使用表达式 *(rain + year) + month
遍历给定行的元素
.
如果你只想使用指针重写循环,那么它们可以看起来像
const float ( *rain_ptr )[MONTHS];
const float *month_ptr;
float total = 0.0f;
for ( rain_ptr = rain; rain_ptr != rain + YEARS; ++rain_ptr )
{
// for each year, sum rainfall for each month
float subtot = 0.0f;
for ( month_ptr = *rain_ptr; month_ptr != *rain_ptr + MONTHS; ++month_ptr )
{
subtot += *month_ptr;
}
printf("%5d %15.1f\n", 2010 + rain_ptr - rain, subtot);
total += subtot; // total for all years
}
当然,如果编译器允许,则无需在循环之前声明指针。最好在循环语句中声明它们。