目录
地址
" 地址 "是内存区中对每字节的编号(地址指向内存单元)
指针
声明变量时,会在内存中为变量分配一个" 地址 ",通过访问这个" 地址 "就可以找到对应的变量,这个变量的" 地址 "为该变量的" 指针 "
变量的" 地址 "为变量的" 指针 "
" 指针 "可以" 指向 "变量、数组、字符串、函数以及指针
访问
存取变量值的方法大致分为" 直接访问 "、" 间接访问 "两种
直接访问
" 直接访问 "是通过变量" 地址 "存取变量值的方式
间接访问
将" 变量地址 "存放在另一个变量中,先找到存放变量地址的另一个变量(通过另一个变量找到变量地址)的,为" 间接访问 "
指向
星号" * "关键字表示" 指向 "," 指向 "的行为由" 地址 "实现
变量
变量的" 地址 "是变量和" 指针 "之间连接的纽带
若变量(a)包含了变量(b)的地址,则变量(a)指向变量(b)
int a;int b;
a+b; /*根据变量标识符与变量" 地址 "的对应关系,找到变量" a "的" 地址 ",并从其地址位向后读取4字节数据,存放到CPU的某一寄存器中; 再找到变量" b "的" 地址 ",从其地址为向后读取4字节数据,存放到CPU的另一寄存器中;最后CPU的加法中断计算出结果*/
//在" 低级语言 "、" 汇编语言 "中,都是直接通过" 地址 "来访问内存单元的
指针变量
" 指针变量 "是指向变量" 地址 "的变量(" 指针变量 "用来存放另一个变量的" 地址 ")
声明
声明指针变量的格式,包括:" 类型说明 "、指针变量声明关键字" * "、" 变量标识符 "三个部分
类型说明 *变量标识符 /*类型说明代表指向变量的数据类型,关键字" * "代表此声明变量为" 指针变量 "*/
char _a;
char *a=&_a;
char _b;
char *b;
b=&_b; /*如果已经声明指针变量,再调用时不要带关键字" * "*/
" 指针变量声明关键字 "与" 指针运算符(取值运算符) "不同;" 指针变量声明关键字 "为" 关键字 ",而" 指针运算符(取值运算符) "是" 运算符 "
赋值
指针变量的值,只能为" 指针 "类型
使用地址运算符" & "取出地址
char a;
char *p = &a;
不允许把" 数 "赋值给指针(只能为" 指针 "类型)
调用
调用指针变量是对变量进行间接访问
*指针变量;
*a; /使用" 指针运算符(取值运算符) "*调用指针变量所" 指向 "的值*/
自增自减
指针变量的" 自增自减 "是根据指针变量所指向地址的" 直接长度 "进行增加或减少的(地址的" 直接长度 "由" 数据类型 "决定)
int a;
int *p=&a;
p++; /*一般有符号整数类型的" 直接长度 "为4字节,指针" p "向后移位4字节(自加)*/
p--; /*一般有符号整数类型的" 直接长度 "为4字节,指针" p "向前移位4字节(自减)*/
数组指针
" 数组指针 "为指向数组的指针变量
在内存中,数组的标识符保存的是其在内存空间的" 首地址 ",若将数组的首地址传给指针变量,则指针变量指向对应数组
int *p,a[1];
p=a; /*数组标识符" a "为数组的" 首地址 ",指针" p "被赋值并指向" a "数组内存空间的" 首地址 "*/
int *p,a[3];
p=a[0]; /*" a[0] "是数组" a "的首地址,即操作与" p=a; "相同*/
指针变量直接调用数组标识符时,目标数组一定要进行定义(确定数组元素个数),否则无法调用第一个数组标识符(数组标识符=数组第一个元素的地址)
调用数组元素
用指针的方式调用数组元素,需要采用" 目标数组表示符 "+" 偏移地址 "的方法,先得到数组元素地址,最后用" 取值运算符 "取出
int *p,a[5];
p=a+2; /*对于" 地址 "使用加法运算符或减法运算符,则是进行偏移多少" 直接长度 "的字节(最终值为地址)*/
printf("%d",*p);
调用二维数组元素与调用一维数组元素方法相同(存储空间中皆为一行数据)
int num[5][3]={
{1,2,3},
{1,2,3},
{1,2,3},
{1,2,3},
{1,2,3}
};
int *p1,*p2,*p3;
p1=&num[0][0];
p2=num+9;
p3=num;
for(int i1=0;i1<5;i1++)
{
for(int i2;i2<3;i2++)
{
printf("%d\n",*p3++);
}
}
printf("%d\n%d",*p1,*(p2+2));
字符串指针
调用字符可以是指针的方式
char *string="biboli"; /*声明字符型指针变量" string "并赋初值字符串常量(将字符串的第一个字符的" 地址 "存放到指针变量中)*/
printf("%s",string);
char *string;
string="biboli";
printf("%s",string);
char *string;
#define _string "biboli"
int count=strlen(_string);
string=_string;
for(int i=0;i<count;i++)
{
printf("\n%c",*string++);
}
指针数组
数组元素皆为指针类型(指针变量)的数组,为" 指针数组 "
类型名 *指针数组标识符[数组长度]
char *string[]=
{
"biboli",
"king",
"weijunjie"
};
for(int i=0;i<3;i++){printf("%s\n",string[i]);}
" 字符串指针数组 "可以直接存储字符串
二层指针
" 二层指针 "变量,一种指向指针的指针变量,又叫" 指针的指针 "
" 二层指针 "变量的声明定义结构包括:" 终值数据类型标识符 **二层指针变量标识符"
终值数据类型标识符**二层指针标识符;
int **p; /*根据结合性,等同于" int *(*p); ";声明定义指针变量" p "," p "指向另一个指针变量,最终指针变量所指向的值为" 基本有符 号整型变量 "*/
如果需要不同情况调用多个不同的指针变量,就用" 二层指针变量 "
char *string[3][3]=
{
{"biboli","1","king"},
{"king","2","weijunjig"},
{"weijunjie","3","biboli"}
};
for(int x=0;x<3;x++)
{
for(int i=0;i<3;i++){printf("%s\n",string[x][i]);}
}
char **p[3],*s1[7],*s2[7],*s3[8];
char s1={'b','i','b','o','l','i','\n'};
char s2={'k','i','n','g','w','e','\n'};
char s3={'i','j','u','n','j','i','e','\n'};
p={s1,s2,s3};
do
{
printf(*p++);
}
while(33);
指针函数
返回指针的函数简称为" 指针函数 "
函数在编译时会被分配1个入口地址,这个函数入口地址,就是函数的" 指针 "
可用一个指针变量指向函数,然后通过该指针变量调用此函数
声明定义指针函数的表达式结构,包括:" 函数返回值类型 *函数标识符(形式参数列表); "
返回值类型 *函数标识符(形式参数列表);
int *fun(int x,int y); /*调用" fun "指针函数能得到一个指向整型数据的指针(返回的指针指向整型变量)*/
指针形参
指针型变量也可以作为函数参数
指针类型变量也可以作函数返回值
指针也可以指向函数
main指针形参
运行C程序时,源文件中的主函数main作为程序的入口函数,在命令行状态运行C程序时,主函数main以及其实际参数,是一并传递的
命令名 参数 参数2 参数3 ... 参数n
D:\software\test.c biboli king wjj /*命令行中的命令名就是可执行文件的文件名*/
指针数组" argc "记录了命令行中命令与参数的个数,指针数组的大小由参数值决定
main(int argc,char *argv[]) /*参数字符串长度不定,参数字符串长度不统一,参数字符串数目任意*/
函数指针
指针可以指向函数,函数在编译时会被分配一个入口地址,函数入口地址就被称为函数的指针
数据类型 (*指针标识符)(形式参数列表);
int a(int,int);{print("biboli");return b;}
int (*p)(int,int);
p=a; /*函数指针的" 返回类型 "、" 形式参数列表 ",要与被指向函数保持一致(否则指向失败)*/
将指向函数的指针可以作为函数的参数
int a(int a,int b,int (*p)());