zoukankan      html  css  js  c++  java
  • C语言---指针

    C语言中对变量的访问有两种方式:

    1)直接访问,通过变量名;

    2)间接访问,通过地址来访问某一个变量,该变量的地址是另一个变量的内容。

    事实上,程序经过编译后,对变量的访问都会变为从地址的访问。

    printf("%d ", i);

    scanf("%d ", &i);   //scanf语句使用&i来访问

    一个变量的地址称为该变量的指针,地址被形象的称为指针,如果一个变量专门用来存放另一变量的地址,它被称为

    "指针变量",指针变量的值---是另一个变量的地址,指针变量的地址---是本身变量的地址。

    定义指针变量:

    类型名   *指针变量名;

    int *point_1;

    int *point_2 = &b; //定义时,初始化

    指针变量名前的"*"表示变量为指针变量,point_1的值表示另一变量的地址,*point_1表示另一变量的值

                                                            &point_1表示该指针变量的地址

    定义指针变量时,必须制定基类型,因为访问一个变量不但需要知道首地址,还需要知道访问的字节数。

    &取地址运算符; *指针运算符

    指针在调用指针运算符,对另一变量赋值的时候,必须先对指针的值进行初始化,否则,指针指向的地址未知,容易发生错误。

    int * temp;

    *temp = *p1;   //容易产生错误

    当指针变量作为函数参数时,它表示将一个变量的地址传送给另一变量。 

    void swap(int *ptr1, int *ptr2) {

      int *temp;

      temp = *ptr1;           //输入指针交互各自内容,temp可以定义为普通int变量

      *ptr1 = *ptr2;

      *ptr2 = temp;

    }

    void swap(int *ptr1, int *ptr2) {

      int *temp;

      temp = ptr1;        //输入指针各自指向的地址交换

      ptr1 = ptr2;

      ptr2 = temp;

    }

    数组名作为函数的实参传递时,也是表示指针的传递。

    void main () {

    fun(array,10);

    }

    void fun(int arr[], int n) {

    }

    实参用指针、数组表示,形参用数组、指针表示都是等价的。

    通过指针引用数组。数组本身也是一种特殊的指针:

      int a[10];

      int *ptr;

      ptr = &a[0];  //C语言中数组a[10]的地址,可以用&a[0]或者a来访问

      ptr = a;  //与&a[0]等价

    数组元素的引用:

    下标: a[i];

    指针:*(a+i)

    *(p++),表示先取*p的值,然后p自加1;

    *(++p),表示p先自加1,然后再取*p的值;

    C语言中,字符串是存放在字符数组中的,有两种表示方法:

    1) 用字符数组存放一个字符串,通过数组下标引用某个字符,%s+数组名输出整个字符串,%c+数组下标输出某个字符

       char string[] = "I am a big man"

       printf("%s ",string);

       printf("%c ",string[4]);   //最后一个字符存放""

    2) 用指针变量指向一个字符串常量

       char *string = "I am a big man"

       等价于 char *string;  string = "I am a big man"   //对字符指针的访问不需要加"*"

    指向函数的指针,系统编译的时候,编译系统会为子函数代码分配一段存储空间,这段存储空间的起始地址称为这个函数的指针。

    int (*p) (int,int)表示指向一个返回值为int,且有两个int 参数的函数。

    所以函数的调用可以使用函数名直接调用,也可以通过函数指针来调用。

    int main() {

      int max(int, int);    //函数声明

      int (*p)(int, int);     //函数指针声明

      int a,b;

      p = max;  //使得P指向max函数

      c = (*p) (a,b);  //通过函数指针调用函数

    }

    返回指针的函数定义:  类型名  *函数名(参数列表)

    float *search (float *point, int b)   //返回值为float *类型的指针

    指针数组:一个数组,其中的每个值都是指针变量,类型名 *数组名[数组长度]

    int *p[4];  //[]优先级比*高,所以先形成p[4]形式,后加*p

    int (*p)[4];  //表示指向一维数组的变量

    动态分配内存空间,

    void  *malloc(unsigned int size);  //分配大小为size字节的连续空间,赋值时,最好强制转换指针类型。

    void  *calloc(unsigned n, unsigned int size);  //分配n个连续的size字节大小的连续空间,赋值时,最好进行强制类型转换。

    void  *free(void *p);  //释放指针p指向的已分配的动态空间。

    void  *realloc(void *p, unsigned int size);  //已分配过的地址,重新改变其大小。将p指向的地址,改为size大小。

    将void类型的指针赋值给不同的基类型的指针变量时,不需要用户进行强制类型转换,编译系统会自动进行转换。

    链表是一种常见的动态分配内存的结构。

    链表由很多节点组成,每个节点,包括两部分,1)用户实际的存储数据,2)下一个节点的地址。

    链表都有一个头指针,"head",只存放一个地址,指向下一个数据元素。最后一个节点的地址指向null

    使用结构体来建立链表是比较合适的。

    struct Student {int num;

                           float score;

                           struct Student *next;}

    静态链表的建立:   //静态链表,存储空间在编译时,已经是定死的

    struct Student a,b,c,*head,*p

    head = &a;

    a.next = &b;

    b.next = &c;

    c.next = null;

    动态链表的建立:

    struct Student * creat(void)  {  //返回一个指向struct Student类型的指针

     struct  Student  * head;

     struct  Student *p1, *p2;

     n = 0;

     p1 = p2 =(struct Student *) malloc(LEN);

     scanf("%ld, %f", &p1->num, &p2->score);   //输入第一个同学的分数

     while(p1->num != 0)  {           //直到输入的num为0,停止

      n = n+1;

      if(n==1) head = p1;

      else p2->next = p1;   //p2中指向的是,新的内存空间的入口

      p2 = p1;   //p2被赋值为p1   //将p2表示为上一次的节点地址。

      p1 = (struct Student *) malloc(len);  //p1是每次重新分配的内存入口

      scanf("%ld, %f", &p1->num, &p2->score);   //输入下一个同学的分数

      }

    数组指针与指针数组,[]的优先级高于*(p);

    数组指针:int (*p)[n],也称为指向一维数组的指针,

      int (*p)[4];定义一个数组指针,指向含4个元素的一维数组,每次加一,是增加4个byte。

      int a[3][4];

      p = a;

      p++,该语句执行结束之后,p=p+1,p直接指向a[1][0]

    指针数组:int *p[n],本身也是一个数组,但是数组中的数据,都是指针,

      赋值的时候,需要注意,*(p[n]) = num,作为指针进行赋值。

    数组指针,只是一个特殊的指针,专门用来指向一个二维数组,

    指针数组,是一个指针的list,多个指针,连续的存放在内存中。

  • 相关阅读:
    pat乙级1034
    getline()读入一整行
    c++ 输入split
    13.缓存、三级缓存、内存溢出、AsyncTask
    12、json、GridView、缓存
    11.webview、shareSDK
    10.下拉刷新、加载更多、标记已读、轮播条、缓存
    9.indicate、xutils、json
    8.滑动事件处理
    7.ViewPagerIndicator
  • 原文地址:https://www.cnblogs.com/-9-8/p/6664981.html
Copyright © 2011-2022 走看看