指针
Ⅰ.指针与指针大小的概念
C程序设计中使用指针可以:
①动态分配内存
②使程序简洁、紧凑、高效
③有效地表示复杂的数据结构
④得到多于一个的函数返回值
1.内存地址:内存中存储单元的编号 例:信箱是内存 信箱格是存储单元 信息编号是内存地址
2.变量地址:程序编译或函数调用时为变量分配的内存单元起始地址,内存大小由变量的数据类型决定
&取地址符 sizeof获得变量和数据类型所占内存大小(字节数)
#include <stdio.h>
void main()
{
int a = 20;
printf("sizeof(int) = %d\n", sizeof(a)); //输出a的字节数
printf("&a=0x%08x\n", &a); //输出变量的地址 0x%表示输出十六进制的a 08x表示占八位右对齐不足位补零
}
改程序运行后,会输出
sizeof(int) = 4
&a=0x0018ff44
3.指针和指针变量
指针:变量的地址,常量。
指针变量:专门存放变量地址的变量。
Ⅱ-1.指针变量的定义和引用
定义 指针变量 [存储类型] 数据类型 *指针变量名;
存储类型是指针变量本身的存储类型 auto static register extern
数据类型是指针变量指向的内存单元的数据类型,就是目标变量的数据类型。
指针变量名是标识符
例子:
const int *p; //定义指针变量p 指向整型常量 即变量p中存放的是一个整型常量的地址
char *pc,ch; //定义字符型指针变量pc,字符变量ch
static double *dptr; //定义浮点型指针变量dptr dptr是静态变量
char *p1, *p2; //定义字符指针变量p1, p2
Ⅱ-2.指针变量的赋值
指针变量定义后,变量值不确定,必须先赋值,再使用
①通过赋值语句赋值 指针变量名 = &变量名(指针)
②初始化赋值 [存储类型] 数据类型 *指针变量名 = 初始地址值
例子:
int *iPtr; //定义整型指针变量
int iCount = 18; //定义整形变量
iPtr = &iCount; //将iCount的地址存放到iPtr中
int iCount. *iPtr = &iCount;
指针变量注意事项:
原则上一个指针变量只能指向同类型的变量,可通过强制类型转换。在变量前加上 (类型)
Ⅱ.3指针变量的引用
间接引用:通过指针变量间接引用指向的变量的值。
格式: *指针变量, *是间接引用运算符
*p = 10; //把10赋值给p指向的内存空间
Ⅲ.指针和地址运算
指针是地址,是一种无符号整型。
指针变量p与n的加运算 p ± n 的值 = p ± n * sizeof(ptype) ;
#include <stdio.h>
void main()
{
int *pi;
char *pc;
long *pl;
pi = (int *)1000;
pc = (int *)1000;
pl = (int *)1000;
pi++; // pi=pi+1=pi+sizeof(int)=pi+4=1004
printf("sizeof(int)=%d, pi=%d \n",sizeof(int), pi); //4 1004
pi -= 2; // pi=pi-2=pi-2*sizeof(int)=pi-2*4=996
printf("pi=%d \n", pi); //996
pc++; // pc=pc+1=pc+sizeof(char)=pc+1=1001
printf("sizeof(char)=%d, pi=%d \n",sizeof(int), pi);
pc -= 2; // pc=pc-2=pc-2*sizeof(char)=pc-2=999
printf("pi=%d \n", pc); //999
pl++; // pl++=pl+1=pl+sizeof(long)=pl+4=1004
printf("sizeof(long)=%d, pi=%d \n",sizeof(int), pi);
pl -= 2; // pl=pl-2=pl-2*sizeof(long)=pl-8=996
printf("pi=%d \n", pl); //996
}
#include <stdio.h>
#define N 4
void main()
{
int a[N] = {10,20,30,40}, i;
int *p = &a[0];
for(i=0; i<N; i+=2, p+=2)
printf("p=0x%08x, address(a[%d])=0x%08x\n", p, i, &a[i]);
}
两个指针的减运算
p,q指向同一数组 p-q = (p-q)/sizeof(ptype);
#include <stdio.h>
#define N 4
void main()
{
int a[N] = {10,20,30,40};
int *p = a, *q = &a[2];
printf("p=0x%08x, q=0x%08x\n", p, q); //p=0x0018ff38,q=0x0018ff40
printf("p-q=%d\n", p-q); //p-q=-2
printf("q-p=%d\n",q-p); //q-p=2
}
Ⅳ.指针和数组
1.数组的指针
数组的指针是数组在内存中的起始地址。
数组的指针: 数组名、数组第一个元素的地址
假设已定义int a[3] = {10,20,30};
一下输出数组所有元素的语句是否正确。
2.指向数组的指针变量
假设已定义
int a[N], *p = a; //int*p=&a[0];
p+i = p+sizeof(int)*i
a[i]的地址 &a[i]、a+i、p+i
a[i]元素值 a[i]、*(a+i)、*(p+i)、p[i]
#include <stdio.h>
#define N 5
void main()
{
int a[N];
int i, sum, *p;
printf("input %d numbers : ", N);
for(i=0;i<N;i++)
scanf("%d", A+i); //输入数组
for(sum=0, i=0; i<N; i++)
sum += A[i]; //数组下标
printf("sum=%d\n", sum);
for(sum=0, i=0; i<N; i++ )
sum += *(A+i); //数组的指针
printf("sum=%d\n", sum);
for(sum=0,i=0; i<N; i++)
sum += p[i]; //指针变量 sum += *(p+i)
printf("sum=%d\n", sum);
for(sum=0,p=A; p<A+N; p++)
sum += *p; //移动指针变量
printf("sum=%d\n", sum);
}
3.指向多位数组
①利用一般指针变量访问多维数组
p+1 = p+sizeof(int); //移动1个整数,与一维数组对应
a[i][j]的地址引用 a[i][j]的值引用
&a[i][j] a[i][j]
p+i*N+j *(p+i*N+j) / p[i*N+j] / *(a[0]+i*N+j)
//利用一般指针变量引用二维数组元素
#include <stdio.h>
void main()
{
int a[2][3] = {{1,2,3},{4,5,6}};
int i, j, *p;
p = &a[0][0]; //p指向数组第一个元素
for(i=0;i<2;i++)
for(j=0;j<3;j++)
printf("a[%d][%d]=%d\n", i,j, *(p+i*N+j));
}
//利用行指针变量来访问多维数组
int a[M][N] ; //假设已定义M、N
表示形式 含义
a 二维数组首地址,第0行首地址
a+i 第i行首地址
a[i], *(a+i) 第i行第0列的元素地址
a[i]+j 第i行第j列的元素地址
行指针是一种特殊的指针变量,专门用于指向一维数组。
定义格式 (*行指针变量名)[常量表达式];
p[i]+j *(p[i]+j) p[i][j]
*(p+i)+j *(*(p+i)+j) (*(p+i))[j]
//利用行指针变量引用二维数组元素
#include <stdio.h>
void main()
{
short int a[2][3]={{1,2,3},{4,5,6}};
short int i, j, *p[j];
p = a; //p赋值为a的数组指针,第0行指针 也可写成p=&a[0]
for(i=0;i<2;i++)
for(j=0;j<3;j++)
printf("a[%d][%d]=%d\n", i, j, p[i][j]);
p++; //当p赋值为第一行指针时
for(j=0;j<3;j++)
printf("%d ", p[0][j]); //输出第一行数据元素
}
4.元素为指针的数组-指针数组
指针数组:数组元素均为指针
定义格式: 数据类型 *数组名[常量表达式];
指针数组和数组指针的区别:
指针数组 数组指针
定义格式 int *p[20] int(*p)[20]
变量性质 p是数组名 不可以对p赋值 p是指针变量 可对p赋值
空指针:指针变量的值为0的指针,该指针变量没有意义 *p=0/NULL
//利用指针数组对键盘输入的5个整数进行冒泡排序
#include <stdio.h>
void main()
{
int i, j, t;
int a, b, c, d, e;
int *p[5]={&a,&b,&c,&d,&e}; //定义指针数组,分别指向abcde p[i]是地址 *p[i]是值
printf("input 5 numbers :\n");
scanf("%d&d&d&d&d",p[0],p[1],p[2],p[3],p[4]);
for(i=0;i<5;i++)
for(j=0;j<5-i;j++)
if(*p[j]>*p[j+1])
{
t=*p[j];
*p[j]=*p[j+1];
*p[j+1]=t;
}
printf("sorted:\n");
for(i=0;i<5;i++)
printf("%d ",*p[i]);
}
Ⅴ.指针与字符串
用字符数组表示字符串 char str[]="ok"; //用于字符数组初始化,不占空间
printf("ok\n"); //字符串常量、占空间、有起始地址
1.字符指针定义
char *字符指针变量名=字符串常量(边定义边赋值) char *pstr = "ok!";
char *字符指针变量名; 字符指针变量名=字符串常量;(先定义后赋值) char *pstr; pstr="ok!";
2.字符串的引用
①单字符引用 pstr[i]
②整体引用 int len=strlen(pstr); printf("%s" ,pstr);
//使用字符串指针变量按正序、逆序分别输出字符串
#include <stdio.h>
#include <string.h>
void main()
{
char *pstr="Hello World !";
int i;
printf("%s\n", pstr); //整体引用,输出字符串
for(i=strlen(pstr)-1;i>=0;i--)
printf("%c ", pstr[i]); //单字符引用,逆序逐渐输出
printf("\n");
}
3.字符指针变量与字符数组的比较
4.字符串指针数组与字符串二维数组
char str[3][10]={"Shenzhen","Guangzhou","Xianggang"}; //字符串数组
char *pstr[3]; //pstr 一维数组 3个指针
pstr[0] = str[0];
pstr[1] = str[1];
pstr[2] = str[2];
char *pstr[3] = {"Shenzhen","Guangzhou","Xianggang"};
pstr[0] -> Shenzhen
//利用字符串指针数组对城市名进行升序降序
#include <stdio.h>
#include <string.h>
void sort(char *[], int n); //对字符指针数组指向的城市名升序排序
void output(char *p[], int n); //输出城市
void main()
{
char *pcity[] = {"Bei","Shang","Guang","Shen"}; //定义字符指针数组,分别指向Bei等字符串
int n;
n = sizeof(pcity)/sizeof(char *); //利用sizeof运算符计算得到数组pcity的大小
sort(pcity, n); //对pcity指向的城市升序排序
output(pcity, n); //输出排序后的结果
}
void sort(char *p[], int n) //void sort(int a[], int n)
{
int i, j, flag;
char *temp;
for(flag=1,i=1; i<n && flag;i++) //冒泡排序
for(flag=0,j=0; j<n-i; j++) // flag=0 用于排序优化
if(strcmp(p[j], p[j+1])>0) //p[j], p[j+1]指向的串反序,串比较用strcmp
{
temp = p[j]; //交换地址
p[j] =p[j+1];
p[j+1] = temp;
flag = 1; //利用flag优化排序。
}
}
void output(char *p[], int n) //void output(int a[], int n)
{
int i;
puts("Sorted : \n");
for(i=0; i<n; i++)
puts(p[i]); //整体引用传
}
pcity[0]->Bei
pcity[1]->Shang
pcity[2]->Guang
pcity[3]->Shen
数据类型 a[100];
void sort(数据类型 a[], int n);
char *pcity[]={"Bei","Shang","Guang","Shen"};
void sort(char *pcity[], int n);