数组
char a[n];n为整性或整性表达式时就不是一个可变长度的数组,反之则这个数组是可变长度的;(c99)
字符数组可以用字符串格式一次性打印。
//赋值方式: char a[]="abcde"; int a[10]={1,2,3};//没有赋值到的均为0; int a[]={1,2,3,4,5};//自动计算长度 int a[10]={[3]=3,[5]=5,[8]=8};//指定赋值 //二维数组: int a[2][3]={1,2,3,4}; int a[2][3]={{1,2},{3}}; int a[2][3]={[0][1]=1,[0][2]=2,[1][0]=3}; int a[][3]={1,2,3,4,5,6,7};//可以不写行数,但列数必须写明
指针
变量存放数据,指针存放地址;
指针占用的内存都是4个字节,不像变量(int(4),char(1),float(4),double(8));【取址:&a;取值:*a;】
int a=1;int *b=&a; //赋值如果不为地址,则指针指向整型数据所表示的指定位置 //地址的占位符是%p
数值名
是一个地址信息(数组名是一个指针常量),而且还是数组第一个元素的地址;所以【数组/指针】也可以用【指针/数组】的方式访问元素。
数组只能分开访问每一个元素(每一个元素都是左值),不可以访问整个一块数组;(函数名也有类似性质)
//指针和数组名的区别:指针是一个左值(变量,用于存放地址),而数组名是一个地址常量 (右值); int a,b,c=0; int *p[3]={"asdf","qwer","czxnh"};//指针数组:一个存放只指针的数组; int (*p)[3];//数组指针:指向数组的指针(指针移动的单位为数组大小) //赋值时,将数组的地址赋给他:int (*p)[3]=&一维数组名
数组指针和二维数组
二维数组
每个元素都是一维数组;所以二维数组名是第一个一位数组的地址;
int array[4][5]; array==array[0]; *(array+1)==array[1]==&array[1][0]; //均为地址,前面再加一个*才可取出这个位置的值 //即:*(*(p+i)+j)==p[i][j];
数组指针
int (*p)[5]=array;
指向数组的指针
数组指针移动的单位为数组大小:*( *( p+i ) + j ) == p[ i ][ j ];
void(无类型)指针和NULL(kong)指针
void *p:无类型指针,可以指向任意类型的数据;解引用时需要强制类型转换;*(int *)p;
NULL 指针:不指向任何数据:【其实NULL是一个宏定义:0; #define NULL ((void *)0) 0地址一般不会被指向】;
当定义指针后不知道指向那个地址时就可以指向NULL【int *p=NULL;】
二级指针
存储指针的地址;【一层解引用只为一个指针的地址】
因为二级指针指向指针,二级指针移动的单位为指针大小(4个字节)
int **p1,(*p2)[4];//p1为二级指针,p2为数组指针; *(p1+1)-*p1=4;//因为二级指针指向 int 指针,所以跨度为4 *(p2+1)-*p2=16;//因为这个数组指针指向一个长度为4的 int 数组,所以跨度为16
注:终上所述,数组指针指向一个数组时,有*(*(p2+i)+j)==array[i][j];而二级指针则不会有这种性质。
常量和指针
1、宏定义:define A ‘a‘
2、使用 const 关键字(只读不写):const float pai=3.14;
指向常量的指针
const int *p; //指向常量的指针,指向常量。不可以改变通过解引用修改指向地址的值;可以通过修改指向不同的常量来间接修改解引用的值 int * const p; //指向常量指针,指向变量。不可以改变通过解引用修改指向地址的值;可以修改指向变量的值来间接修改解引用的值 const int * const p; //指向常量的常量指针;【指向常量的指针也是可以指向变量的】
原文:https://www.cnblogs.com/TianLiang-2000/p/12713005.html