进一步认识数组
a是数组,a和&a是什么
对于数组int a[5] = {1, 2, 3, 4, 5};
,a
表示数组首元素的地址,而&a
表示数组的首地址
a
有两层含义:
-
a
表示数组首元素的地址(类型为int*) -
a
表示一个大小为5的int数组
数组名本身在计算中会自动转化成第一个元素的地址,但sizeof测试的时候不做计算,不转化。由此可以看出,在计算*(a + 1)
的时候,可以把a
看成int*
类型的指针,a + 1
表示的是数组第二个元素的指针,由此*(a + 1)
的值为2。但是sizeof(a)
是把a
作为一个数组类型来测试大小,结果是数组占用的字节数,由此sizeof(a) = 20
&a
是一个指向int(*)[5]
的指针。由于&a
是一个指针,那么在32位机器上,sizeof(&a)=4
。但是&a + 1
的值取决于&a
指向的类型,由于&a
指向int(*)[5]
,所以&a + 1 = &a + sizeof(int(*)[5]) = &a + 20
。&a
是数组的首地址,由此&a + 1
表示a
向后移动了5个int
从而指向a[5]
。由此可知,(int*)(&a + 1)
指向了数组a
最后一个元素之后的下一个内存单元开始的4个字节
数组的下标可以为负数吗
可以,因为下标只是给出了一个与当前地址的偏移量而已,只要根据这个偏移量能定位到目标地址即可,只是它表示的意思是从当前地址向前寻址,即为当前地址减去sizeof(类型)
的地址值
不使用流程控制语句,打印1~1000的整数
方法一
采用构造函数与静态向量结合的方法实现。首先在类中定义一个静态成员变量,然后在构造函数里打印该静态变量的值,并对静态变量的值进行自增操作,同时在主函数里定义一个类数组,代码如下:
#include <iostream>
using namespace std;
struct print
{
static int a;
print()
{
cout << print::a++ << endl;
}
};
int main()
{
print tt[1000];
return 0;
}
方法二
可以通过使用宏定义来实现
#include <stdio.h>
#define A(x) x;x;x;x;x;x;x;x;x;x;
int main()
{
int n = 1;
A(A(A(printf("%d", n++))));
return 0;
}
行存储与列存储的效率
有数组a[M][N]
,下面哪种算法效率更高
1)
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
xxx = a[i][j]...
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
xxx = a[j][i]...
上述两种方法中,方法1)的效率要高一些,C++采用的是行存储策略,数组是一行一行地存的,方法1)是行存储,所以效率更高