数组加指针是什么?
int *a[10];
这里定义了一个什么呢?
指针加数组,那不就是指针数组.yes,看上去很简单
但如果定义成下面呢
int (*a)[10];
数组指针?指针数组?似乎有点乱了.这两个似乎并不是同一回事,怎么区分呢?
指针数组
指针数组是数组,数组内的元素类型是指针.
定义形式如下
int *a[10];
可以发现和我们平时定义变量的形式很不同.
数组指针
数组指针是指针,它指向一个数组.
形式如下
int (*a)[10]
可以发现数组指针和指针数组定义的形式很相似,但是意义却有着天壤之变.
如何区分
我们区分它们的方法很简单,就是通过优先级判定,例如
int *a[10];
由于[]的优先级比*高,所以a先和[10]结合,这就是一个数组.
其实这样写更一目了然
int* a[10]
int a[10]
可以发现它俩都是数组,一个是int类型的数组,一个是int*类型的数组
int (*a)[10];
int *a;
这里给a加上(),就改变了它的优先级,a先和 结合所以它就是一个指针.指向了 int[10]一个整型数组.
有了上面的规则,我们可以玩点花的
int (*(*a[10]))[10] ;
这是一个数组指针 指针数组,
再详细的解释一下就是:
1. 这个数组里有十个元素;
2. 其中每个元素都是一个数组指针
3. 其中的指针指向一个有10个整型变量的数组
定义这种变量有什么实际意义吗?
答案是十分重要,
因为这是一种秀操作的好方法.
除此之外并无什么用处,
但是不会耍帅还当什么程序员呢?
接下来如果把数组当作指针用,把指针当作数组用,会发生什么呢?
定义是让不存在的存在,而声明是让不知道的知道
我们有了上面这句话,就可以研究一下指针和数组在声明和定义上的关系了
把定义的数组声明成指针
我们在test.c文件中定义一个数组
char p[] = "abcdefg";
然后在
main.c文件中把它声明为一个指针,在以字符串的形式输出.
extern char*p;
int main()
{
printf("%s\n", p);
getchar();
}
我们通常会认为这里肯定是正常操作
输出”abcdefg”这个字符串.
但是!运行起来我们会发现程序崩溃了?!!!!
why??
因为我不可能把正常操作写出来 :)
因为我要秀操作.
我们有一个假设,p已经不指向原来’abcd’的字符串了,而指向了一个0x64636261 内存的位置,而这是一个非法内存.
但为什么会指向一个 64 63 62 61数值这么奇怪的一个内存地址呢?
思索一番,发现64 63 62 61就是原来字符串中 ’ abcd’的ASCII值,不过反过来变成’dcba’了.
接下来我就要给大家解释一下了
首先,定义一个变量会开辟内存空间存放这个变量,而声明不会这样做,只是告诉编译器有这么一个变量,对应了开头我们所说的
定义是让不存在的存在,而声明是让不知道的知道
我们在main.c 声明 char *p ,
那编译器就知道了有这么一个变量,
就会去test.c里找这个变量所在的内存地址,然后把里面的值取出来.
但是main.c中把p当成了char*,是一个指针,只有四个字节,所以里面只存放了”abcdefg”中的前四个字节,也就是’abcd’
接下来,因为p是一个指针,所以指针里面应该存的是地址,就把’abcd’当作了地址去访问,崩溃是自然的事情了.
最后一个问题,为什么*p中的值是’bcda’,而不是’abcd’呢?
这牵扯到一个”大端,小端”的问题,我们的电脑只要是intel处理器的,就默认是小端,即数据的低字节存放在地址中的低地址处,
“abcd”字节大小一次增大,所以地址从高到低应该是”bcda”
定义指针声明成数组
同样的,我们在test.c中定义一个指针
char *a = "abcdefg";
然后在main.c中把其声明成一个数组
extern char a[];
int main()
{
printf("%d\n", a[0]);
printf("%d\n", a[1]);
printf("%d\n", a[2]);
printf("%d\n", a[3]);
getchar();
}
由于在main.c中认为a是一个字符数组,所以其中每个元素应该只有一个字节,
然后去test.c中找a,因为发现a是一个指向”abcdefg”的指针,
那么a是一个存有这个字符串首地址,四个字节大小的指针变量.
把这个装入main.c中的数组,
因为数组元素大小为一个字节,所以装入四个字节大小的指针变量,需
要四个元素,
最后这个数组的四个元素拼接起来就是”abcdefg”这个字符串的首地址.
结尾
感谢观看!