C指针专题1

一.如何理解指针?

1.    首先指针是一个变量,既然是变量就有它的目的,变量的目的就是来存放数据。不同的是指针变量存放的数据是另一个变量的地址,其实不光可以存放变量的地址,还可以存放函数的地址,指针变量的地址。

    指针既然是变量,就有它所属的数据类型。指针所存储变量的类型,就称为指针的类型。

    例1,有三个不同的变量:
int A,*PI=&A;             PI++;
Char B,*PC =&B;      PC++;
Float C,*PF=&C;       PF++;
请问右边的三个运算有何不同?

2.研究指针的三要素:指针本身的地址?指针指向的地址?指针指向的地址里面的内容?

3.指针本身的大小也就是指针变量占用的存储空间,与所用的CPU寻址空间和类型有关,而与指针类型无关。

   8位CPU的指针长度一般为1~3个字节,16位CPU指针长度一般为2个字节,32位CPU指针长度一般为4个字节。

4.数组作为函数的形参时,会降为指针来用。

  void arrayTest(char str[]) 

printf(“%d”, sizeof(str); //arrayTest(str)打印为4

Char str[] = ‘hello”; 

5.空指针是特殊的指针,它可指向任何的指针类型。一个变量指向空指针,表示当前指针处于空闲状态,不指向任何地址。同时任何不用的指针一定要指向空指针,否则就会有野指针存在。

6.野指针不是NULL指针,是指向不明内存的指针。野指针的成因:

   1).指针变量没有被初始化;

   2).指针P被free或delete之后,没有置为NULL;

   3).指针操作超越了变量的作用范围;

注:C标准承认指针在指向数组元素的时候,它所指向的元素可以大于数组元素的个数,发生指向越界的现象,而且编译器可能不会报错。

二.一维数组与指针

1.数组中每一个元素都可以被寻址,这是和能指针结合的关键。

2.数组中的地址有哪些表示方式?

例:int a[10]; 

        int *p=a;   

   1).a是一个常量地址,等价于&a[0],&a[0],&a[1].....&a[i]等都是代表地址。但&a是错误的,这里相当于取地址的地址了。a是一个指针常量,在程序运行期间不能改变,所以a++,a--,是无法实现的。

   2).C语言规定数组名(不包括形参数组名,形参数组并不占据实际的内存单元)代表数组中的首元素的地址。

   3).指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。

   4).根据以上的定义,有一下的等价概念:

 p+i,a+i,&a[i]它们等价于同一个地址;

*(p+i),*(a+i),p[i],a[i]它们等价于同一个地址里面的内容;

   5).*p++。由于++和*同优先级,结合性为自右而左,因此等价于*(p++),先得到*P的值,在自加1。

       *(++p)作用是先p加1,在取*p的值。

       ++(*p)作用是p所指向的元素值加1,p的地址没有变过。

3.当用数组名做为形参时,如果形参数组中各元素发生变化,实参数组中元素的值随之也对应发生变化。常用这种方法通过调用一个函数来改变实参数组的值。实参数组名代表一个固定的地址,或者说是一个指针常量。而形参数组名并不是一个固定的地址,是一个指针变量,它的值等于实参数组首元素的地址,在函数执行期间,它可以被赋值改变。

4.如果两个指针Px和Py所指向的变量类型相同,Px-Py所执行的运算不是两指针所存的地址值相减,而是(Px-Py)/数据长度,即是一个整数。

5.可变长数组。我们知道数组的长度在程序运行时,是不能改变的,但我们可以通过指针的方式,来变相的实现一个可变长的数组。

例如:

int  *variable_array;

variable_array=malloc(sizeof(int)*size);


三.程序举例

题目一:用指针变量输出一个数组所有的元素?

四种写法注意比较。

#include<stdio.h>

void main(void)

{

int a[10];

int *p,i;

for(i=0;i<10;i++)

   scanf(" %d",&a[i])//注意不要丢掉了&取地址运算符

for(p=a;p<(a+10);p++)//留心指针与for循环的结合,不要写成for(p=a;p<10;p++)

   printf("%d",*p)

}


#include<stdio.h>

void main(void)

{

int a[10];

int *p=a,i;

for(i=0;i<10;i++)

   scanf(" %d",p++)//注意不需要& ,也不需要*

p=a;

for(i=0;i<10;i++,p++)//留心指针与for循环的结合,不要写成for(p=a;p<10;p++)

   printf("%d",*p)

}


#include<stdio.h>

void main(void)

{

int a[10];

int *p=a,i;

for(i=0;i<10;i++)

   scanf(" %d",p++)//注意不需要& ,也不需要*

p=a;

for(i=0;i<10;i++)//留心指针与for循环的结合,不要写成for(p=a;p<10;p++)

   printf("%d",*p++)

}


#include<stdio.h>

void main(void)

{

int a[10];

int *p=a,i;

for(i=0;i<10;i++)

   scanf(" %d",p++)//注意不需要& ,也不需要*

p=a;

while(p<a+10)

   printf("%d",*p++)

}



题目二.编写一个函数,实行对数组a中n个整数按相反顺序存放?

比较两种写法。

void  contrary(int a[ ],int n)

{

int i,temp;

for(i=0;i<=(n-1)/2;i++)    //注意这里的循环次数

    {

     temp =a[i];

     a[i] = a[n-i-1];

     a[n-i-1] = temp;

    }

}


void  contrary(int *a,int n)

{

int *i,*j,temp;

for(i=a,j=a+n-1;i<=a+(n-1)/2;i++,j--)    //注意这里的循环次数

    {

     temp =*i;

     *i = *j;

     *j = temp;

    }

}


题目三.编写一个函数用选择法对给定的数组进行由大到小的排序?

比较两个程序,同时注意区别穷举法。

void  sort(int x[ ],int n)

{

int i,j,k,t;

for(i=0;i<n-1;i++)

   {

   k=i;

   for(j=i+1;j<n;j++)

      if(x[j]>x[k]) k=j;

  if(k!=i)

       {t=x[i];x[i] =x[k];x[k]=t;}

   }

}


void  sort(int *x,int n)

{

int i,j,k,t;

for(i=0;i<n-1;i++)

   {

   k=i;

   for(j=i+1;j<n;j++)

      if(*(x+j)>*(x+k)) k=j;

  if(k!=i)

       {t=*(x+i);*(x+i) =*(x+k);*(x+k)=t;}

   }

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值