指针

Ⅰ.指针与指针大小的概念

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.指向数组的指针变量

假设已定义

 

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);

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值