[C语言]当数组结合指针,会迸发出什么火花?我相信这火花会让你头晕目眩!!

数组加指针是什么?

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”这个字符串的首地址.

结尾

感谢观看!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值