数组
一个数组的类型是由其元素的类型和数量决定的。在描述一个数组的时候我们一定要描述出他的类型和数量。例如:int a[10]={}
定义了一个int型的10个元素的数组。数组的定义决定了数组名.元素类型以及元素的个数 。
参照上一个例子ar
表示的是该数组的首地址。
void fun(int *b,int n)
{
}
int main()
{
int a[10]={};
fun(a,10);
}
//此处传进去的是首地址,由于数组是由数组名,元素个数构成,所以此处也要给与一个个数n
指针
指针的定义
计算机中的数据都必须在内存中存放,不同类型的数据占用的字节数不一样,例如int占4字节,char占1字节。为了正确的访问这些字节,必须对其进行编号,每个字节的编号是唯一的,根据编号可以准确地找到某个字节,我们将内存中字节的编号称为地址或指针,地址从0开始依次增加,对于32位环境,程序能使用的内存为4GB。(最小的地址为0x0000 0000,最大的地址为0xFFFF FFFF )。
*的作用:1.表示乘法。2.表示定义的一个指针变量。3.表示指针所指向的数据,是一种间接操作。
2.定义指针变量
int*p;//int *p=&a;二者等价
p=&a;
指针变量存放的是内存地址,使用*号来访问地址的值,指针的大小在32位平台是4个字节,在64位是8个字节
3.空指针和野指针
空指针int *a=nullptr;
空指针可通过assert()来断言。
#include<assert.h>
assert(ptr!=null);
野指针就是没有给指针初始化的指针,这样的指针绝对不要出现。
指针的运算:
1.指针+整性(不可以是浮点类型)
int main()
{
const int n=5;
int ar[n]={12,23,34,45,56};
int *ip=&ar[0];//int *ip=ar;
for(int i=0;i<;++i)
{
printf("0x%08x=>%d\n",*ip,*ip);
ip=ip+1;
}
printf("\n");
return 0;
}
指针+1详解:
int*ip=ar;
ip=ip+1;
其实是ip的地址加上sizeof(int)*1;
指针的类型不同,加1的能力也不一样
指针和整型加减后的结果仍然是指针类型
2.指针+指针(不可以进行这样的运算)
3.指针-指针;
表示的是两个指针间的距离,这只有在指向同一个数组的时候才有用,可以用关系运算符>,==,!=等进行比较,比较规则是后面元素的指针高,指向同一元素的相等。
int ar[10]={};
int *ip=ar[4];
int *ip2=ar[6];
ip2-ip1;就是二者的距离
若是*ip2-*ip就是二者指向的数据相减。
int main()
{
int ar[5]={12,23,34,45,56};
int *p=ar;
int x=0;
int y=0;
x=*++p;
y=*p;
printf("%d %d\n",x,y);//23,23
x=++*p;
y=*p;
printf("%d %d\n",x,y);//24,24
x=*p++;
y=*p;
printf("%d %d\n",x,y);24,34
return 0;
}
指针与数组的关系
1.数组名被看作该数组第一个元素在内存中的首地址(仅在sizeof函数中例外,在sizeof中被看成是整个数组的内存大小)。数组名在表达式中被自动转换为一个指向数组第一个元素的指针变量。
数组名是指针很方便,但却会丢失数组的大小,这会带来无法预知的严重错误。ar[i]被编译器解释为*(ar+i)所以i[ar]就是*(i+ar)。这两中表示是一样的。
用数组做函数的形参时,数组将退化为指针类型。
退化为指针 是为了节省他的时间效率和空间效率,这样形参就不必再开辟多余的空间了。
void print_array(int br[],int n);
void print_array(int br[5],int n);
void print_array(int *br,int n);//都一样的
指针变量与const
const可以修饰指针
const int *p=&a;//表示指针变量所指向的数据不可变(即不能修改指向的值)
int*const p=&a;//表示指针变量本身的值不可变。(即对指针进行初始化后便不可再变其指向)
无类型指针void*
使用void常见的两种情况是:
当函数不需要返回值时,必须使用void限定:void fun(int a)
当函数不需要参数时,当然现在只要设定为int fun()就行。
void不能定义变量 但可以定义指针。由void定义的指针可以指向任何类型变量的地址。甚至它还可以指向自己。
在ANSI C标准中,不允许对void指针进行一些算术运算如
int a=10;
void *vp=&a
不可以vp++或者vp+=1
但在GNU中,确实允许vp++的,因为在默认情况下 GNU认为void*和char*一样
二维数组与二级指针
int **p,p为二级指针,指向int*类型的数据。
int *p[n],p是数组,数组的元素是int指针。
int (*p)[n]为指向大小为n的数组的指针。
int ar[4] = { 12,23,34,45 };
int(*s)[4] = &ar;//&ar指的是整个数组的地址
此处将其与二维数组相联系 注意二维数组可看成由n个一维数组组成的,