C语言数组与指针(重要)

A. 数组:同一类型的多个元素集合;在使用数组前必须先声明以开辟需要的内存空间

(1)为每个数据分配存储空间;

(2)能对每个数据进行读写和查找;

注:数组占据的内存空间是连续的

如:一个大小为N,类型为short的数组,其占据的内存大小为:N*sizeof(short)=N*2

如果第一个地址为p,那么第M(M<=N)在内存中的地址可表示为:p+(M-1)*2,这充分体现了数组的有序性

   例子:

#include<stdio.h>

#include<conio.h>

void main(void)

{

       int score[6];  //声明一个int型数组,大小为6

       int sum=0,i=0;

       double averagescore=sum;//计算平均成绩

       printf("请依次输入6名学生的成绩\n");

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

       {

              scanf("%d",&score[i]);//读取操作

              sum+=score[i];  //总成绩

       }

       averagescore=sum/6.0;

       printf("平均成绩:%.1f",averagescore);

       getch();

}

其中,数组可以放6个元素,范围是0-5,“%d.1f”为了只输出一个小数。

 

数组的初始化:没有初始化的数组,存在安全隐患,不好查错。可以只初始化其中一部分,如果都初始化为零,可以直接等于零、

 

二维数组: int num[2][3]={{1,0,0},{2,0,0}};

 

B. 指针

内存是由按顺序编号的一系列存储单元组成的,在内存中,每个存储单元都有唯一的地址,通过地址可以方便的在内存单元中存取信息。内存的数据要靠供电来维持。

内存地址是连续的,相邻内存单元间的地址相差1,相当于一个平坦连续的一维空间。

计算机中,信息以二进制数据存放,每个内存单元容量是1B=8bit(8个0、1的二进制位)

中央处理器(CPU)执行程序时,即是对复杂的内存载入的过程

(1)程序所要进行操作的对应代码被装载到代码区;

(2)全局和静态数据等装载到数据区;

(3)开辟堆栈,供临时变量等使用。

内存中的数据:可以是数据、程序。

 

指针变量:该变量的值是一个地址(无符号的整形数)

     如:int a=10,x,*p=&a;称指针变量p指向整形变量a

注:*为指针标识符

地址就是指针

指针:存储的内容是地址的量。(指针变量占据一定的内存空间)注:指针是个量,对应着一块内存区域;指针存储的信息是某个内存单元的地址。

声明一个指针变量(开辟内存空间):(1)指针的类型;(2)指针变量名;

形式:类型* 指针变量名;

指针的值不确定,即取决于指针所占内存区域的值,是随机的,故指针变量需要初始化,如果不知道指向何处,需置“”,关键字NULL;如:int* a=NULL;

指针变量的值:地址,不是一般的数值;如:“一个指针的值是A”指该指针指向了以A为首地址的一片内存区域

取地址操作符&:返回实体的地址信息;如:

int num=0;

int* p=&num;

&num返回的是变量num在内存中的地址信息,可以直接将此地址赋值给同类型的指针p。

指针变量占据一定的内存空间(32位系统都是占据4字节内存空间)

例子:

#include<stdio.h>

#include<conio.h>

void main()

{

     int a=0;

     short b=0;

     double c=0;

     int* d=&a;

     short* e=&b;

     double* f=&c;

     printf("int型占据的内存字节数:%d\n",sizeof(a));       //4

     printf("指针int型占据的内存字节数:%d\n",sizeof(d));  //4

     printf("short型占据的内存字节数:%d\n",sizeof(b));     //2

     printf("指针short型占据的内存字节数:%d\n",sizeof(e));  //4

    printf("double型占据的内存字节数:%d\n",sizeof(c));   //8

     printf("指针double型占据的内存字节数:%d\n",sizeof(f));//4

     getch();

}

指针变量所占内存不变,指向的变量所占据内存与其无关。

 

指向指针的指针:指针变量也是变量,占据内存空间,有地址,因此也可以用一个指针指向它,即二级指针,用“**”声明,如:

double num;

double*a=&num;

double**b=&a;

 

“*”的作用:“类型*”是一种复合类型,用来声明某种类型的变量,另一作用:间接引用,即通过指针访问其指向的内存区域。

形式:

double num=9;

double* a;

a=&num;

注:

(1)num:double类型的变量;

(2)a:指向num的指针变量,其值是num的地址;

(3)&num:返回变量num的地址,与a等价;

(4)*a:a所指的变量,间接访问方式,与num等价;

(5)&(*a):与&num(即a)等价,即num的地址;

(6)*(&num):与*a(即num)等价,变量num。

例子:

#include<stdio.h>

#include<conio.h>

void main(void)

{

     int num=9;

     int* a=&num;

     printf("指针变量a的值:%x\n",a);//18ff44

     printf("指针变量a指向的内存区域为:%d\n",*a);//9

     *a=10;

     printf("num变量的值为:%d\n",num);  //10

}

18ff44是int型变量num的地址

 

注:指针类型与指针所指向的类型可以使相同的,也可以是不同的。

(1)同类型指针的赋值

     例子:

#include<stdio.h>

#include<conio.h>

void main(void)

{

       int num=9;

       int* a=&num;

       int* b=a;

       *a=10;  //通过指针改写其指向的内存区域

       printf("num变量的值为:%d\n",num);  //10

       *b=11;  //等价于*a=11

       printf("num变量的值为:%d\n",num);  //11

       getch();

}

*a与*b与num是等价的。

 

 

(2)指针的类型和指针所指向的类型不同

   A.指向内存的字节数大于指针类型占据的字节数

      doublenum;

int* a=&num;    //*a为int型,而num是double型

double num;

double*a=&num;

int* b=a;

B.指向内存的字节数小于指针类型占据的字节数

   short num;

   double* a=&num;

   或

   short num;

   short* a=&num;

   double* b=a;

注:指针的类型决定可通过指针间接访问的区域;对于A中,尽管double型变量占据8个字节,但指针是int型,故只能管理前4个字节;对于B中,short型数据占2个字节,儿double型指针管理的是8个字节,这时,short型数据后边的6个字节会被指针改写,这种“越权”会给程序带来致命的错误。

(3)不同类型但占据相同字节

会出现奇怪的结果。

 

指针的运算:

主要是加减算术运算和特殊运算;

两个有关的运算符:(&与*)

     &:任意变量   //取地址运算符

     *:指针变量   //指针运算符

     &a 表示变量a所占据的内存空间的首地址

     *p 表示指针变量p所指向的内存中的数据

     x=*p;内容,相当于x=a 

     *p=100;内容

 

   例子:用指针交换两个单元中的内容

#include<stdio.h>

void main(void)

{

       inta,b,c,*p1=&a,*p2=&b;

       scanf("%d%d",p1,p2);

       c=*p1;

       *p1=*p2;

       *p2=c;

       printf("a=%d,b=%d\n",*p1,*p2);

}

输出交换以后的a和b

 

一、指向简单变量的指针

int a,b,c,*p1=&a,*p2=&b;

注意区分:

(1)p1=p2与*p1=*p2;

   (2)(*p1)++与*p1++;

   (3)&*p等价于p;*&a等价于a

解释如下:

1P1=P2 :把P2的地址赋给P1,此后P1P2都指向b;(原来是P1指向a);

*P1=*P2:把P2所指向的内容放到P1所指向的单元,此后ab都等于b的值;

2)(*P1++ *P1=a,故(*P1++相当于a++

*P1++ :如果a的地址为1000,则*P1++指向1001,即指向a后边的变量(a后边的变量不知道是什么,故*P1++没有意义);

3&*P=P   *&a=a  :其中*P=a    &a=P注意:*后边一定是指针变量(因为指针变量才能进行指针运算);&后边一定是普通的变量.

 

二、指向数组的指针

 (1) int a[10], *p=a;      &&p指向a数组的首地址  等价于:  p=&a[0]

数组名a就表示数组的首地址,故不需要&

 

 

(2)数组元素的地址:  &a[i]   a+i    p+i

解释如下:a表示数组首地址;故其他的可以直接用a+i

 

(3)数组元素的内容:a[i]   *(a+i)    *(p+i)

 

(4)指向数组的指针p的运算:p+/-I    p-qp++p—p>q

     注:p+/-i表示p是指向数组,数组是一个空间,p可以在数组中移动i;

        p-q表示p和q都是指向同一个数组,则p-q表示他们之间相差的个数;

        p++指向p后边一个元素,p—往前移;

        p>q  p和q指向同一个数组,p指向的元素在q后边。

   a+i ;p-a;但 a++a—是错的,因为a不是一个变量。

(5)指针与函数参数:

      形参是指针变量时,实参可以是数组名、指针变量

三、字符串指针变量

char *sp=“abcdef”,str[10], *PP=str;

char表示指针变量是指向字符型数据

即sp指向字符串的首地址

注:字符串指针变量和字符数组的区别(谭浩强P238页)

 

   例子:将字符串倒序存放’

  方法一:

#include<stdio.h>

#include<string.h>

void main()

{

    char c,str[100];

    int i=0,j;

    gets(str);  //输入字符串

    j=strlen(str); //计算数组长度

    j--;

    while(i<j)

    {

           c=str[i];

           str[i]=str[j];

           str[j]=c;

           i++;

           j--;

    }

    printf("string=%s\n",str);  //%s字符串输出

}

 方法二:(用指针变量做)

    #include<stdio.h>

#include<string.h>

void main()

{

       charc,str[100],*p=str,*q;

       gets(p);

       q=p+strlen(p)-1;

       while(p<q)

       {

              c=*p;

              *p=*q;

              *q=c;

              p++;

              q--;

       }

       printf("string=%s\n",str);

}

注释:

 q=p+strlen(p)-1;

Strlen(p)取长度,(如果输入“China”,则长度为5),因为下标从零开始,故需要减1;

 

故有:p指向首地址,q指向最后一个元素;如下图:

while(p<q)

       {

              c=*p;

              *p=*q;

              *q=c;

              p++;

              q--;

       }

当p<q时,不需要交换了

 

 

       printf("string=%s\n",str);此时不能输出 p,因为p已经移动而变化了。

 

例子:编写一个函数:将字符串src中的字符复制到dest中。

函数说明:int a(char *dest,char *src)或int a(char dest[],char src[])

方法一:

  Voida(char dest[],char src[])

{

           int j =0;

while((dest[j++] = src[j]!=’\0’));

}

判断是否结束标记“\0”,最后结束标记也已过去了

方法二:

void a(char dest[],char src[])

{

       char*p=src;

       char*q=dest;

       while(*q++=*p++);

}

方法三:这是错的(因为数组名dest不是变量,故不能自加运算)

void a(char dest[],char src[])

{

       while(*dest++=*src++);

}

方法四:

void a(char *dest,char *src)

{

       intj=0;

   while((dest[j++]=src[j])!=’\0’);

}

指针变量也可以用下标

方法五:

void a(char *dest,char *src)

{

       char*p=src;

char *q=dest;

while(*q++=*p++);

}

 

方法六:

void a(char *dest,char *src)

{

       while(*dest++=*src++);

}

数字名不能自加,这里是指针变量,是变量,指向后面的元素,故可以

 

 

例子:求字符C在字符串中首次出现的位置(用指针、函数方法做)

//用指针做

#include<stdio.h>

#include<string.h>

int a(char *p,char x)

{

       inti=0,k=-1;

       for(;*p!='\0';p++,i++)

              if(*p==x)

              {

                     k=i;

                     returnk;

              }

              returnk;

}

void main()

{

       chars[100],y;

       intb;

       gets(s);

       //y=getchar();  //输入要判断的字符

       y='c';  //判断c首次出现的位置

       b=a(s,y);

       if(b>=0)

              printf("position=%d\n",b);

       else

              printf("notexit\n");

}        

注:

  输入一个字符串用gets(s);   输入一个字符用y=getchar();s为是第一个出现的地址。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值