zoukankan      html  css  js  c++  java
  • [转载]C 指针

    一、认识存储单元
     
    指针是C语言最显著的特色。要理解指针的概念,需要先理解计算机读写内存的的方式以及变量的概念。
     
    计算机内存是以字节为单位划分内存单元的,每个内存单元占用一个字节,每个内存单元都有自己的地址编号,操作系统或软件根据这个地址来识别内存单元,在地址所标识的内存单元中存取数据。内存单元的地址是固定的,内存单元中的数据是可以修改的。
     
    C语言中,变量名实质上是内存单元的地址符号,用户使用变量本质上是访问该变量所对应的内存单元。
     
    二、C指针的概念
     
    1、在C中,将内存单元的地址(编号)称为指针,可以通过一个变量来存放指针,这种变量称为指针变量。指针变量中存储的是内存单元的地址。
     
    例如 int a = 10; 假设存放a的内存单元块为 101,102,103,104,占用四个字节。如果再执行一个 int *p=&a;那么p的值就成为101了,*p的值就是10,a的值也是10。
     
    &是取地址运算符,获取变量的首地址。
     
    2、创建指针的方法是:类型说明符 *变量名,这是C定义指针变量的方法。其中*表示这个变量是指针变量。
     
    C要求,指针必须存放在指针变量中。
    一个指针只能指向同一类型的变量。
     
    3、指针的初始化
    int *p=NULL;
    int a=10;
    int *p=&a;
     
    注意:
    a)未初始化的指针的系统会给一个随机的值,没有意义,操作可能引起系统崩溃。
    b)未初始化的指针应该给一个NULL值,以表明它是个空指针,表示0值。
    c)不允许把常量赋值给指针变量。
    d)必须保持指针变量类型与所指数据的一致性,否则会发生不可预期的效果。(虽然C已允许将任何地址赋值给指针变量)。
     
    4、取地址& 与 取内容*
     
    取地址运算符是& ;
    取内容运算符是*,注意:区别定义指针变量类型说明符*。
     
    int a=10;
    int *p=&a;    //定义指针变量p,并指向a;
    *p=3;   //将3赋给指针p所指的内存单元,则a的值也变为了3
    int b = *p;  //将指针p的所指内存单元值赋给变量b;
     
    明白这个道理后,指针和一般变量一样可以操作了。
     
    指针的直接操作内存,在Java中是没有的,Java没有指针。Java中的基本变量名实际上也是内存地址的别名。
     
    三、指针操作数组
     
    1、指向数组的指针
     
    数组是保存在一片连续的内存单元中。数组名是这块连续内存单元的首地址,是不可改变的常量。因此数组名也是一个常量指针。
    int a[3]={1,2,3};
    int *p=a;  //指向数组的指针
     
    当指针执行数组名或数组首元素地址时,指针就指向了数组。
     
    2、指针运算
    a)自增/自减:C规定,指针加1,表示指针后一个指针的类型的内存单元。
    b)加减整数运算,只能加减整数,整数表示的基类型数据的宽度倍数。
    c)指针相减,指针间的元素个数,不是存储单元数。
    d)指针比较,判断指针在内存中的高低位置关系。
     
    3、指针操作数组
     
    下标发和指针法,分五种方式:
     
    #include<stdio.h>
    int main()
    {
            int i,a[5]={1,2,3,4};
            int *p=a;
            for(i=0;i<4;i++)
                    printf("a[%d]=%d\n",i,a[i]);
            printf("\n");
            for(i=0;i<4;i++)
                    printf("p[%d]=%d\n",i,p[i]);
            printf("\n");
            for(i=0;i<4;i++)
                    printf("*(p+%d)=%d\n",i,*(p+i));
            printf("\n");
            for(i=0;i<4;i++)
                    printf("*(a+%d)=%d\n",i,*(a+i));
            printf("\n");
            for(i=0;i<4;i++)
                    printf("*p++=%d\n",*p++);
            getch();
            return 0;
    }
     
    a[0]=1
    a[1]=2
    a[2]=3
    a[3]=4

    p[0]=1
    p[1]=2
    p[2]=3
    p[3]=4

    *(p+0)=1
    *(p+1)=2
    *(p+2)=3
    *(p+3)=4

    *(a+0)=1
    *(a+1)=2
    *(a+2)=3
    *(a+3)=4

    *p++=1
    *p++=2
    *p++=3
    *p++=4
     
    注意,数组名虽然是指针,但是数组名是常量,不可改变,因此不可以a++;
     
    4、指针操作二维数组
     
    二维数组是多个一维数组组成的数组,或者说是一维数组的数组,或者说是一维数组,但是各个元素还是一维数组。
     
    这个概念和java中是一致的。
     
    假设有二维数组
    int a[x][y];
    那么
    a)a表示数组首地址的指针。
    b)a[i]表示第i+1个一维数组,其地址为a[i],指向的是一个一维数组。
    c)a[i][j] 与*(a[i]+j)、*(*(a+i)+j)是相同的,表示同一个元素。
     
    #include<stdio.h>
    int main()
    {
            int a[4][5], i,j;
            for(i=0;i<4;i++)
                    for(j=0;j<5;j++)
                            a[i][j]=i*5+j;
            printf("二维数组的值为:\n");
            for(i=0;i<4;i++)
            {
                    for(j=0;j<5;j++)
                            printf("%4d ",a[i][j]);
                    printf("\n");
            }                

            getch();
            return 0;
    }
     
    二维数组的值为:
         0        1        2        3        4
         5        6        7        8        9
        10     11     12     13     14
        15     16     17     18     19
     
     
    5、数组指针
     
    数组指针:变量是指针,指向了一个数组。
    例如:
    int *p[3];定义了一个指针p指向了一个长度为3的int数组。
     
    #include<stdio.h>
    int main()
    {
            int a[4][5],i,j;
            int (*p)[5];
            p=a;
            for(i=0;i<4;i++)
            {
                    for(j=0;j<5;j++)
                            *(*p+j)=i*5+j;
                    p++;
            }
            printf("二维数组的值为:\n");
            p=a;
            for(i=0;i<4;i++)
            {
                    for(j=0;j<5;j++)
                            printf("%4d    ",*(*p+j));
                    printf("\n");
                    p++;
            }                

            getch();
            return 0;
    }
     
    二维数组的值为:
         0        1        2        3        4
         5        6        7        8        9
        10     11     12     13     14
        15     16     17     18     19
     
    6、数组名参数
     
    指针变量 p 是空指针的判断:
    if ( p == 0 )
    if ( p == '\0' )
    if ( p == 3 - 3 )
    if ( p == NULL )  /* 使用 NULL 必须包含相应的标准库的头文件 */
    if ( NULL == p )
    if ( !p )
    if ( p == q )
    ...

    指针变量 p 不是空指针的判断:
    if ( p != 0 )
    if ( p != '\0' )
    if ( p != 3 - 3 )
    if ( p != NULL )  /* 使用 NULL 必须包含相应的标准库的头文件 */
    if ( NULL != p )
    if ( p )
    if ( p != q )
  • 相关阅读:
    IP地址分类
    Python 加密 shellcode 免杀
    java翻译到mono C#实现系列(2) mono实现GridView 横向滚动
    Hello Jexus(转并修改)
    @using (Html.BeginForm())和@{Html.BeginForm();}@{Html.EndForm();}对比
    FindLine把多行查找改为多行替换
    java翻译到mono C#实现系列(1) 重写返回键按下的事件
    mono 的System.Data.SqlClient小记录
    架构文件夹说明
    Xamarin Mono For Android 4.6.07004看不到新建android
  • 原文地址:https://www.cnblogs.com/fx2008/p/2159520.html
Copyright © 2011-2022 走看看