zoukankan      html  css  js  c++  java
  • 谭浩强C指针(一)

    一、地址指针的基本概念
    计算机中所有数据存放在存储器中,一般将一个字节称为一个内存单元。C语言中整型数据占两字节,即两个内存单元;字符型数据占一个内存单元。为准确访问内存单元,须给内存单元编号,这编号也称为地址。指针就是对地址的描述。数据或函数在内存中都是连续存放的,通过指针指向的首地址可以找到数据或函数。
    二、变量的指针和指向变量的指针变量
    1、变量的指针就是存放变量的存储单元的首地址。
    2、C语言中可用一个变量来存放指针,这种变量称为指针变量。
    3、指针变量的定义及运用:
    (1)定义:
    类型说明符 *变量名;//类型说明符说明的是该指针变量指向内存单元存放的数据类型,字符*表示该变量是一个指针变量
    (2)指针变量的运算
    1)&:取地址运算符:对变量x取其地址:&x.
    2)*:指针运算符:对指针变量x取出其指向内存段中的数据:*x.(须注意这里运算符*与指
    针变量中说明符*的区别。
    (3)指针变量初始化
    1)定义中直接赋值:
    int a;
    int *p=&a;
    2)单独赋值(不能把直接数、常量赋值给指针变量):
    int a;
    int *p;
    p=&a;
    4、指针变量作为函数参数
    如果指针变量作为函数的参数,则在调用时讲实际参数(实际指针变量的值)传给形式参数指针变量,但一般情况下,与一般的实际参数一样,在调用之后实际参数本身的值不发生变化,实际指针变量参数的值也不变化,即不改变实际指针变量的指向地址。因为调用函数时仅仅是实际参数向形式参数传递值而已,不影响本身。
    5、指向其他数据类型的指针变量
    (1)指向数组
    int a[2],*pa;
    pa=a; //数组名表示数组的首地址
    pa=&a[0]; //另外一种写法,因为数组第一个元素的地址即为数组首地址
    (2)指向字符串
    char *pc;
    pc="clanguage"; //将字符串"clanguage"首地址给pc
    (3)指向函数入口
    int (*pf)()
    pf=f; //f为函数名称
    ?疑问1:
    对于指向数组的指针变量为何用int定义?按理解int *定义的指针变量指向的内存单元存放的是基本整型数据。如果这样定义,用(指针运算符*+指针变量)表示的究竟是整型数据还是数组呢?

    疑问例1:

    上例中pa指向数组b,*pa表示第一个数组元素;*(pa+1)表示第二个数组元素。

    那么上面疑问1“如果这样定义,用(指针运算符*+指针变量)表示的究竟是整型数据还是数组呢?”则并不是问题了。因为指向数组的指针变量数据类型须与数组类型一致。
    ?疑问2:
    对于指向字符串指针变量为何赋初值直接写出整个字符串。另外,对于谭浩强书中例子:
    char *pc;
    pc="clanguage";
    如果对于字符串"clanguage"在定义指针变量之前未有定义该字符串会否程序出错?如果未定义,系统怎知忽然冒出的这个字符串的存储地址呢?或是在给pc赋初值的同时就先给字符串分配了存储空间?

    上例显示程序终止,问题在哪里?
    三、理解实例
    1、输入a,b整数,按大小分别输出a和b。

    void main()
    {
    int a,b,x,*pa,*pb,*p;
    printf("input 2 numbers:");
    scanf("%d%d",&a,&b);
    pa=&a;pb=&b;                                    //思考:这里能否用*pa=a;*pb=b;代替?
    if(a<b)  {p=pa;pa=pb;pb=p;}                     //2、只是通过改变指针变量的指向
    printf("a=%d,b=%d.\n",a,b);             //1、存放a和b的内存单元中的数值没有变
    printf("max=%d,min=%d.\n\n\n",*pa,*pb);
    //如果要互换ab的值:
    printf("input 2 numbers:");
    scanf("%d%d",&a,&b);
    if(a<b) {x=a;a=b;b=x;}                //方法一:直接通过中间变量转换
    printf("max=%d,min=%d.\n\n\n",a,b);
    printf("input 2 numbers:");
    scanf("%d%d",&a,&b);
    if(a<b)  {x=*pa;*pa=*pb;*pb=x;}            //方法二:改变指针指向内存单元的值,即改变ab值
    printf("max=%d,min=%d.\n",a,b);
    }

    2、用调用函数方式实现例1功能。

    void maxmin(int *pa,int *pb)
    {
    int *p;
    *p=*pa;
    *pa=*pb;
    *pb=*p;                   //上述转换的只是各指针指向内存单元里的数值,不改变指向;这种方法等同于直接用数值变量
    }
    void main()
    {
    int a,b,*pa,*pb;         //指针变量名与形式参数名一直不引起冲突,因作用域不同
    printf("input 2 numbers:");
    scanf("%d%d",&a,&b);
    pa=&a;pb=&b;
    if(a<b) {maxmin(pa,pb);}
    printf("max=%d,min=%d.\n",a,b);
    }

    引申下段程序:

    void maxmin(int *pa,int *pb)
    {
    int *p;
    p=pa;
    pa=pb;
    pb=p; 
    }
    void main()
    {
    int a,b,*pa,*pb; 
    printf("input 2 numbers:");
    scanf("%d%d",&a,&b);
    pa=&a;pb=&b;
    printf("*pa=%d,*pb=%d.\n",*pa,*pb);       //原数
    if(a<b) {maxmin(pa,pb);} 
    printf("a=%d,b=%d.\n",a,b); 
    printf("*pa=%d,*pb=%d.\n",*pa,*pb);      //调用函数改变的是形式参数指针变量的指向,不影响实际参数指针变量的指向,存放a和b内存单元的值也未受到影响
    }

    3、输入a,b,c三个整数,按大小输出

    void maxmin(int *pa,int *pb)
    {
    int *p;
    *p=*pa;
    *pa=*pb;
    *pb=*p; 
    }
    void main()
    {
    int a,b,c,*pa,*pb,*pc; 
    printf("input 3 numbers:");
    scanf("%d%d%d",&a,&b,&c);
    pa=&a;pb=&b;pc=&c;
    if(a<b) {maxmin(pa,pb);}
    if(a<c) {maxmin(pa,pc);}
    if(b<c) {maxmin(pb,pc);}
    printf("max=%d,middle=%d,min=%d.\n",a,b,c);
    printf("max=%d,middle=%d,min=%d.\n",*pa,*pb,*pc);
    }
  • 相关阅读:
    Restful API 指南
    git submodule 使用小结
    git 在 A 项目中引用 B 项目
    Error Permission denied when running brew cleanup
    @Scope注解设置创建bean的方式和生命周期
    spring常用注解
    Spring的AOP配置文件和注解实例解析
    java线程的状态
    java线程执行的优先级
    java创建线程的方法
  • 原文地址:https://www.cnblogs.com/tsembrace/p/3116150.html
Copyright © 2011-2022 走看看