C语言指针(1)

指针的概念

1、指针的本质就是内存单元地址
①每一个地址代表一个内存单元的地址,地址通常用十六进制数来表示。%p来表示以十六进制数显示数值,十六进制前缀“0x”或者“0X”。
②程序中定义一个变量后,系统会根据这个变量的类型去分配相应字节的内存空间。但是比如我定义一个int类型的变量,系统会给这个变量分配四个字节的空间,那哪个地址是他的地址呢?我该去操作那个地址才能操作这个变量?
变量在内存空间里存放的数据称为变量的值,而系统为变量分配的存储空间的首个单元的地址成为变量的地址
2、直接寻址与间接寻址
CPU访问内存时候有两种寻址方式
① 直接寻址:
例如: int A=35; printf("整型变量A的地址为:%p",&A);
这种&A直接通过CPU直接给出变量的地址的方式
②间接寻址:
例如:int A=35;int *p1=&A; printf("整型变量A的地址为:%p",p1);
间接寻址在程序中不直接获得变量的地址,而是把变量的地址存储到一个指针变量中,然后通过访问该指针变量来访问变量的地址

指针变量的定义


1、定义指针变量
一般形式:
类型说明符 *变量名;

类型说明符表示指针变量所指向的变量的类型,比如你定义了一个int类型的变量A,你想定义一个指针变量P1去指向变量A,那么你定义的指针变量的类型要和A类型相同,因为一个指针只能存储一种数据类型变量的地址。整型的指针变量不能去存储实数型或字符型的数据类型的地址
指针运算符*表示这是一个指针变量,不能和后面变量的名字之间有空格
变量名是定义的指针变量名,命名规则和标识符的命名规则相同
标识符命名规则:
只能由字母、数字、下划线组成,且第一个字母必须是字母或下划线
c语言的关键字不能用作变量名
c语言严格区分英文字母大小写

2、指针变量的赋值
指针变量同普通变量是一样的,使用之前需要定义。指针变量需要赋予具体的地址,即指向一个具体的变量。
未经复制的指针变量不能使用,否则造成系统混乱,指针变量只能赋予地址值,不能赋予其他数据,否则会引起错误
指针变量定义时赋值int A=35; int*p1=&A;
程序运算代码中赋值:int A=35;int *p1;p1=&A;
起初变量p1没有初始化,后来进行的赋值,注意指针变量赋地址时,指针变量名前不能有*。
3、引用指针变量
例如:int A=35;int *p1;p1=&A;*p1=20;
那么此时A的值应该是20.
我们分析一下这个简单的程序。定义了一个指针变量p1,指针变量p1指向了整型变量A的地址。✳p1=20,此时的这个*号代表,取地址指向的内容,所以/*p1现在就是变量A的值35.然后通过 *p1=20进行赋值。
4、指针变量作为函数的参数
举个程序,交换两个变量的值,常规上我们以前时怎么操作的呢

      int main(){
   int A=10,B=20;
   void swap(int a,int b);
   printf("交换前A值为:%d,B的值为:%d\n",A,B);
   swap(A,B);
   printf("交换后的A值为:%d,B值为:%d\n",A,B);
   return 0;}
   void swap(int a,int b)
{   int temp;
 printf("函数中交换前a值为:%d,b值为:%d\n",a,b);
 temp=a;
 a=b;
 b=temp;
 printf("函数中交换后a值为:%d,b值为:%d\n",a,b);
}   

这种可以看出,程序是没有实现A,B两个变量值的交换,原因是非指针变量作为函数形参时,形参得到的只是实参的一个副本。形参的改变不会影响实参的改变

void swap(int *p1, int *p2)
{

在这里插入图片描述

}

void main( )
{ int a,b;
   int *pointer_1,*pointer_2;
   scanf(%d,%d”,&a,&b);
   pointer_1=&a; 
   pointer_2=&b;
   if(a<b)  swap(pointer_1,pointer_2)  ;
   printf(“\n%d ,%d \n”, a, b);
}

当指针变量作为函数的形参时,这时实参赋值给形参的不是变量的值,而是需要复制给形参指针变量为实参变量的地址。

指针与数组

1、数组元素的指针
前面我们已经学习了单个变量的指针和指向单个变量的指针变量,那么我们如何使用指针变量来引用数组元素呢?
一个数组包括若干元素,每个元素都相当于一个单独的变量,每个元素都有相应的地址。
数组元素的指针指的是数组元素占用的存储空间的起始地址。可以用&加数组元素的名字取得,比如,&a[1],代表数组元素a[1]的地址。而数组的地址就是指整个数组连续存储空间的首地址,可以用数组的名字取得,例如a,或者&a[0]。
2、一维数组的地址和指针
①定义一个指针变量指向一维数组
例如 :

 int a[3],*p;
  p=&a[0];或者p=a;

C语言规定:若p指向数组中的一个元素, 则p +1指向数组的下一个元素。
例如:若数组元素是实型,每个元素占4个字节,则p+1使p的原值(地址)加4个字节。

②一维数组元素的表示法

例3:整型数组a有10个元素,可用3种方法输出各元素的值。

1、下标法
 void main( )
{int  a[10];
  int  i;
  for(i=0;i<10;i++) 
       scanf("%d",&a[i]);
  for (i=0;i<10;i++) 
      printf("%4d",a[i]); 
}

⑴地址法:
对于一个数组元素a,数组名a代表该数组的起始地址,且a等价于&a[0];a+i等价于&a[i];a+i所指向的地址内容就是a[i],所以*(a+i)等价于a[i];

       void main( )
{ int  a[10], i;
  for(i=0;i<10;i++)
	scanf("%d",&a[i]);
for (i=0;i<10;i++) 
  	printf("%4d",*(a+i));
printf("\n");
}

⑵指针法:
设a是一维数组,p是一个指针变量,若p的初始值是a,那么p指向数组元素a[0],p+i指向数组元素a[i],因此*(p+i)等价于a[i]。

        void main( )
{ int  a[10], *p=a, i;
  for  (i=0;i<10;i++)
        scanf("%d",&a[i]);
 for (i=0;i<10;i++)
         printf("%4d",  *(p+i)  );
printf("\n");
}
void main( )
{ int  a[10], *p, i;
  for  (i=0;i<10;i++)
        scanf("%d",&a[i]);
 for (p=a;p<(a+10);p++)
         printf("%4d",*p);
printf("\n");
}

③指针变量的移动
指针p移动的长度取决于指针指向的数据类型。
④指针变量的运算
指同一数组的两个指针变量之间可以运算。两个指针变量相减之差是两个指针之间的相对距离(相差数据元素个数),实际上是两个指针值(地址值)相减只差再除以该数据元素的长度(字节数)
例如:(p2-p1)/数据类型所占的字节数=p2与p1之间相差的元素值

指针与函数

一个函数在编译时被分配给一个入口地址,这个入口地址称为函数的指针。 可以用指针变量指向一个函数。
前面学习了指针可以指向变量和数组,那么指针能不能指向函数呢,因为函数是子程序,必定存储在内存的某一部分,必然有一个指向程序第一条指令的地址,此地址为程序的入口地址。
那么程序的那一部分是程序的入口地址呢?
答案是一个函数的函数名是程序的入口地址。
1、指向函数的指针
那么我们就需要一个指向函数的一个指针变量。所以他的定义形式为:
数据类型(*指针变量名)(函数参数列表)
这里的数据类型是这个指向函数的这个指针变量所指向的这个函数的数据类型(返回值)。
例如:int(*p)(int,int)
表示指针p是一个指向函数的指针,函数的返回值是int类型的,并且函数有两个int型的形参变量。
例如:

        void main( )                                                                  
{int max(int,int );
  int  (*p)( int,int);
  int  a,b,c;
  p=max;
  scanf(%d,%d”,&a,&b);
  c=(*p)(a,b);
  printf(“a=%d,b=%d,max%d”,a,b,c);  }
int max(int x, int y)
{int  z ;
 if  (x>y)  z=x ;
 else  z=y ;
 return(z) ;} 

int (p)( ); 说明p是一个指向函数的指针变量,此函数带回整形的返回值。
p=max; 是将函数max的入口地址赋给p 。调用
p就是调用max。
注意:p不能指向函数中间的某处。

*(p)( )表示定义一个指向函数的指针变量。在函数中把哪一个函数的地址赋给它,它就指向哪一个函数。一个程序中,一个指针变量可以先后指向不同的函数。
**4、 在给函数指针变量p 赋值时,只需给出函数名而不必给出参数。如“p=max;”即可, 不能写成”p=max(a,b);”形式。
5、用函数指针变量p调用函数时,只需将(p)代替函数名即可,如“c=(p)(a,b);”表示调用p指向的函数,实参为a,b。
6、对指向函数的指针变量p, p +n, p ++, p- - 等无意义。

补充
指向函数的指针还可以作为一个函数的参数
比如

        main( ) 
{int max(int,int );  
 int min(int,int);
 int add(int,int);
 int  a,b; 
 scanf(%d,%d”,&a,&b);
 printf(“max=);
 process(a,b,max);
 printf(“min=);
 process(a,b,min);
 printf(“sum=);
 process(a,b,add);
}
nt max(int x,int y)   
 {int z; 
if  (x>y) z=x; else  z=y;      return(z);}
int min(int x,int y)    
   {int  z;        
      if (x<y) z=x;  else  z=y;  
   return(z); }
int add (int x,int y)                                      
 {int  z; 
z=x+y;  return(z); }
process (int x, int y, int (*fun)(int,int) )
{int  result ; 
 result=(*fun)(x,y);     
 printf(%d\n”,result); }

2、返回指针的函数
函数运行后可以返回不同类型的值,同样也可以返回指针型的值。返回一个指针值的函数称为返回指针的函数,一般的定义形式为:
数据类型 *函数名(参数列表)
例如 定义一个int *Func(int a,int b),调用该函数会返回一个int型的指针值。
同时“()”的优先级高于“**”,所以这个是表示函数是指针类型的函数,函数的返回值是一个int型的指针。

还有字符串指针和二维数组指针 下次说

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值