一,数组
数组是C语言中一种复合(构造)数据类型,是相同数据类型的一个集合。我们可以把它看作是一个类型的所有数据的一个集合,并用一个数组下标来区分或指定每一个数。
eg:
int a[10]; 说明整型数组a,有10个元素。
float b[10],c[20]; 说明实型数组b,有10个元素,实型数组c,有20个元素。
char ch[20]; 说明字符数组ch,有20个元素。
eg:用for循环将数组初始化为1 2 3 4 5 6 7 8......
int main()
{
int arr[N];
for(int i = 0;i < N;i++)
{
arr[i] = i;
}
}
注:数组名a作为右值时,代表数组首元素的首地址,a不可作为左值。
C/C++中数组是内置的数据类型,但不是基础数据类型而是构造数据类型,语义上是有限个占据连续物理空间的相同数据元素的有序集合。C/C++数组在语言特性上的支持很简单,对应定义的形式T[n] a = {初始化列表};,实际进行的是分配sizeof(T)*n字节的空间,然后使这些空间内的值等于初始化列表中的值而已。分配的空间的回收是隐式的(对于自动变量是在函数结尾,对于静态变量是在进程结束),不需语言使用者干预。动态的线性表或者称为动态数组的数据结构不被C/C++语言特性直接支持,一般通过指针+长度手动调用库函数分配/释放空间,但同样可以通过[]运算符来实现引用其中的元素。对于[],如果不考虑重载,a[x]等价于*(a+x),其中a作为地址,而x是整数偏移量,实质工作(寻址)交给CPU完成。
在定义数组时,如果数组的元素个数不知道的话,只能通过动态内存分配了,静态内存分配是没有办法实现的,因为静态内存分配在定义数组的时候必须指定数组的大小为一个常量或者常数,例如:
int array[10];
或者
const int Size=10;
int array[Size];点击打开链接
二,数组逆置
eg:1.....100的整数逆序输出
#include<stdio.h>
void fun(int a[], int n)
{
int i, temp;
for (i = 0; i <= n / 2 - 1; i++)
{
temp = a[i];
a[i] = a[n - i - 1];
a[n - i - 1] = temp;
}
}
int main()
{
int a[100], i;
int n = 100;
for (i = 0; i < n; i++)
{
a[i] = i;
}
fun(a, n);
for (i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
三,指针
指针是一个地址
eg:int a = 10;
int *p = &a;
*p = 20;
#include <stdio.h>
main()
{
char *pT;
char t='h';
pT=&t;
putchar(*pT);
}
四,指针与数组的联系与区别
五,预防野指针的方法
野指针,不是NULL指针,而是看上去指向合法内存,却在实际上该内存已经释放。
1.声明指针时,记得初始化
eg:char* p=NULL;
2.当指针没有使用价值时,记得释放,释放成功后记得为该指针赋值NULL。
eg:
- if(NULL != P)
- {
- delete p;
- p = NULL;
- }
3.如果指针作为函数的输入参数时,在引用参数前首先对指针进行参数检查。
在函数的入口处使用assert(NULL != p)对参数进行检验,或者用if(NULL != p)来检验。它会提醒指针没有初始化,起到定位错误的功能。assert是一个宏,后面括号里的条件若不满足,则程序会终止运行并提示出错位置。使用完指针后,务必释放该指针所指向的内存。
4.尽量使用引用替代指针。
引用具有指针的功能,同时它还有普通变量的功能。引用对应的变量务必真实存在。引用作为函数的输入参数具有比指针更直接的视觉效果。例如,swap函数的指针实现和引用实现。
5.使用智能指针,避免野指针。
六,sizeof(arr)/sizeof(arr[0])代表什么?
sizeof函数是求对象空间大小的函数。
arry是整个数组,arry[0]是数组中第一个元素
( sizeof(a) / sizeof(a[0]) )代表数组的维数,即计算数组名为a的数组的大小,如果不存在数组名为a的数组就会出错