最近学数据结构,在学数组与指针之间的关系的时候,发现以前一直没理解的一个问题。
首先我们看看数组与指针的一些关系吧。如果我们定义一个数组int a[ ] = {1,1,2,3,5,8,},再把一个指针int *p = a;这句话我们该怎么理解呢?其实很简单,我们只要知道这个语句是定义了一个指向整型数组的指针变量p,并且p指向数组的首地址,后面的就迎刃而解了。而a代表的是数组的第一个元素的地址,我们假设是内存的1000H,那么p指向的就是1000H这个内存地址,那么(a+1)在内存中是什么值呢?是1001H吗?当然并不是这样的,而是1004H,因为我们知道int型变量在内存中占4个字节,那么(a+i)实际指的是a的地址加上i*sizeof(int),所以(a+1)内存中的地址时1004H。
我们知道(a+i)代表第i个元素的地址,同样的道理(p+i)代表的也就是数组第i个元素的地址,*(p+i)就代表数组第i个元素a[i],当然有的书上把*(p+i)写成p[i],另外我们还要知道数组的长度怎么计算,声明的时候我们并没指定数组的长度,但是初始化的时候我们给出了数组的元素,我们可以通过计算得出元素的个数,这里和字符串数组又有些区别,一会我们再看字符串数组的长度怎么计算。有了这些基础知识,我们来具体看一个程序,输出一个数组的所有元素,用函数实现。
#include <stdio.h>
void Show_Array(int * p,int len)
{
int i = 0;
for(i=0;i<len;i++)
printf("%d\n",*(p+i));//*(p+i)=>p[i]=>a[i]
}
int main(void)
{
int a[5] = {1,2,3,4,5};
//int *p = a;
Show_Array(a,5); //a是数组首地址,5是数组长度。<span style="white-space:pre"> </span>
return 0;
}
输出结果是:
1
2
3
4
5
因此我们得出一个结论,一旦我们要输出一个数组中的元素,我们只要知道数组首地址和数组的长度就够了。
我们在来讨论字符串数组与指针的关系。首先我们知道字符串在内存中是以'\0'作为结束的标识符的。因此我们看看下面几种字符串数组声明,长度计算有什么规则。
1.char a[] = {'a', 'b', 'c'};结果是:声明了一个字符数组,长度为3,不会自动添加'\0'。
2.char a[] = "abc";结果是:用字符串去初始化a,要知道,C语言将字符串当做字符数组来处理,所以"abc"本身是有结束字符'\0'的,所以字符数数组长度为4,因为要加上结束字符'\0'。
3.char a[5] = {'a', 'b', 'c'};属于使用“不完全初始化列表”来初始化 a,因为只给出了三个初始化字符,而数组长度为5,最后两个字符自动赋值为0,也就是'\0'。
4.char a[5] = "abc";和上面一个样,长度为5,字符数组(或称为字符串)"abc"将字符数组p的前4个元素赋值,(之所以是4个,因为"abc"本身是包括最后的'\0',会赋值给a),然后最后一个自动赋值为0,也就是'\0'。
5.char a[5] ="abcde";这样声明一个数组在C语言中存在一个异常即数组越界,但是编译器并不报错,但是我们观察输出的结果是abcde烫烫烫这样的乱码。因为abcde加上'\0'总共6个字符,而数组长度只有5,就超过长度了,计算机处理方式以乱码处理。
那么我们怎么输出一个字符串数组呢?我们用程序来说明吧
#include <stdio.h>
void Show_String(char * p)
{
printf("%s\n",p);
while(*p != '\0')
{
//printf("%s\n",p);
p++;
printf("%s\n",p);
}
}
int main(void)
{
char ch[6] = "12345";
printf("%s\n",ch); //%s 输出格式,用于字符串,要求给 字符串的首地址
Show_String(ch);
return 0;
}
输出结果为:
12345
12345
2345
345
45
5
在C语言中%s 输出格式,用于字符串,要求给 字符串的首地址。为什么输出结果是上面的结果呢?
printf("%s\n",ch);在主函数中就输出一次12345
在子函数Show_String()中又输出一次,后面判断有没有到字符串结束标识符,没有到,p自增1,即指向下一个内存地址,因此后面输出的字符都比前面要少一个。所以输出上述结果。