数组
(1)数组:聚合类型,是一组有序数据的集合。
(2)用一个数组名和下标,来唯一确定数组中的元素。
(3)数组中的每一个元素都属于同一种类型。
(4)定义一位数组的一般形式:
类型符 数组名[常量表达式]
- C语言中不允许对数组的大小做动态定义,如
int a[n]
;
(5)引用数组元素的一般形式:
数组名[下标]
(6)一维数组的初始化:
- 未初始化时其值为随机值,初始化后无值的为0;
- 初始化只有一次,赋值时不可以用数组名赋值给数组名,如:arr = brr;
(7)由于局部变量存放在栈中,栈是由高地址向低地址存放,数组存放时先在栈中开辟连续内存,因此,arr[0]在低位,arr[1]在高位;
(8)数组名代表数组首元素的首地址;
- 数组名不能做为左值,我们只能访问数组的某个元素而无法把数组当一个总体进行访问,所以我们可以把a[i]当左值,而无法把a当左值;
- 数组名作为右值代表数组首元素的首地址,意义与&a[0]一样,同样不代表数组的首地址。
- 数组名的含义:
- &arr + 1 -> 数组的长度
- sizeof(arr) -> 数组的长度
- sizeof(arr[0]) -> 数组类型的长度
- sizeof(&arr) -> 数组类型的长度
- sizeof(&arr[0]) -> 数组类型的长度
注:数组中arr –&arr–&arr[0]表示的值是一样的。
(9)在数组中,表示数组长度的方式有:&arr+1;sizeof(arr)/sizeof(arr[0]);
- 仅在数组定义后求长才可以求得长度;
- 在功能函数里不能求长度,arr仅是指针;
补:哨兵位:禁止数组越界,arr与int,int与int相差两个四字节;(VC没有哨兵位,VC中栈是连续的,没有栈保护)
(10)字符数组:
- 字符数组初始化后无值的为’\0’;
- 以字符串形式%s输出时,遇’\0’终止;
例:
char arr[5] = {'d','u','a','n','g'};//输出不停止
char brr[] = {'d','u','a','n','g','\0'};
char crr[5] = {'d','u'};
char drr[6] = "duang";
char err[] = "duang";
printf("%s,%s,%s,%s,%s\n",arr,brr,crr,drr,err);
指针
(1)指针变量里存放的是指向变量的地址。
* 解引用,间接访问符;可以访问指向变量的值。
例:
int a = 10;
int *p = &a;
int **pp = *p;
printf("%d,%d,%d,%d,%d\n",a,p,pp,*p,**p);
*p = 20;
printf("%d\n",a);
**pp = 30;
printf("%d\n",a);
(2)交换函数问题
void Swap1(int a,int b)
{
int tmp = a;
a = b;
b = tmp;
}
void Swap2(int *p,int *q)
{
int *tmp = NULL;//野指针
*tmp = *p;
*p = *q;
*q = *tmp;
}
void Swap3(int *p,int *q)//正确版本
{
int tmp = *p;
*p = *q;
*q = tmp;
}
void Swap4(int *p,int *q)
{
int *tmp = p;
p = q;
q = tmp;
}
void main()
{
int a = 1,b = 2;
Swap1(a,b);
printf("%d,%d\n",a,b);//1,2
Swap2(&a,&b);
printf("%d,%d\n",a,b);//崩溃
Swap3(&a,&b);
printf("%d,%d\n",a,b);//2,1
Swap4(&a,&b);
printf("%d,%d\n",a,b);//1,2
}
分析:
- Swap1函数—>参数传递过程中,只对参数的值进行了传递,所以功能函数内部进行交换操作时,并没有改变主函数参数的值。
- Swap2函数—>功能函数内部产生野指针,野指针没有指向值,tmp解引用时因无值而崩溃;所以
*tmp= *p;
语句不能够执行。 - Swap3函数—>完美执行。
- Swap4函数—>功能函数里的交换操作是对参数的指针来进行操作的,并没有改变参数本身的值。
注:野指针—int *tmp;/ = NULL;
- 指针变量未初始化
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,会乱指一气。
所以指针在创建的同时应当被初始化,要么赋值为NULL,要么让它指向合法内存。 - 指针释放后未置空
指针在free或者delete后未赋值为NULL,free和delete只是把指针所指向的内存释放掉,并没有把指针清除,此时指针指向的为垃圾内存。
为防止野指针,内存释放后,指针应立即指向NULL。