zoukankan      html  css  js  c++  java
  • 初始C语言中的指针(翁凯男神MOOC)

      运算符  &

    ● scanf("%d",&i);

    ●获得变量的地址,它的操作数必须是变量

    ● int i; printf("%x",&i);

    Int i=0;
    printf("%p
    ",&i);

    ● 地址的大小是否与int相同取决于编译器

    &不能取的地址

    ●&不能对没有地址的东西取地址

    ●&(a+b)

    ●&(a++)

    ●&(++a)

    int a[10];
    printf("%p
    ",&a);
    printf("%p
    ",a);
    printd("%p
    ",&a[0]);

    指针

    ●就是保存地址的变量

    int i;
    int *p=&i;

    ●指针指向某一个变量,指针里存放那个变量的地址

    指针变量

    变量的值是内存的值

    ●普通变量的值是实际的值

    ●指针变量的值具有实际值的变量的地址

    作为参数的指针

    void f(int *p);

    ●在被调用的时候得到了某个变量的地址;

    ●int i=0;f(&i);

    ●在函数里面可以通过这个指针访问外面的这个i

    访问那个地址上的变量*

    ● *是一个单目运算符,用来访问指针的值所表示的地址上的变量

    ● 可以做右值也可以做左值

    ● int  k=*p;

    ● *p = k+1;


    指针应用场景

    ●交换两个变量的值

    void swap(int *pa.int*pb)
    {
        int t = *pa;
        *pa=*pb;
        *pb=t;
    }

    ●函数返回多个值,某些值就只能通过指针返回

    void minmax(int a[],int len,int *max,int *min);
    
    int main(int argc, char **argv)
    {
        int a[]={1,231,4,444,33};
        int min,max;
        minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
        printf("min=%d,max=%d
    ",min,max);
        
    
        return 0;
    }
    void minmax(int a[],int len, int *max,int *min){
        int i;
        *min=*max=a[0];
        for(i=0;i<len;i++){
            if(a[i]<*min){
                *min=a[i];
            }
            if(a[i]>*max){
                *max=a[i];
            }
        }
    }

    ●函数返回运算的状态,结果通过指针返回

    ●常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:

    ● -1 或 0 (在文件操作会看到大量的例子)

    ●但是当任何数值都是有效的可能结果时,就得分开返回了

    int divide(int a,int b ,int *result);
    
    
    int main(int argc, char **argv)
    {
        int a=5;
        int b=2;
        int c;
        if(divide(a,b,&c)){
            printf("%d
    %d
    %d
    ",a,b,c);
        }
        
        
    
        return 0;
    }
    int divide(int a,int b,int *result)
    {
        int ret=1;
        if(b==0)ret=0;
        else{
            *result=a/b;
        }
        return ret;
    }

    ●后续的语言(C++ Java)采用了异常机制来解决这个问题

    指针最常见的错误

    ●定义了指针变量,还没有指向任何变量,就开始使用指针

    传入函数的数组成了什么?

    函数参数表中的数组实际上是指针

    ●size of (a)==size of (int*)

    ●但是可以用 数组的运算符[]进行运算

    数组参数

    ●以下四种函数原型是等价的

    ● int sum(int *ar,int n);

    ●int sum (int *,int);

    ●int sum (int ar[],int n);

    ●int sum (int [],int);

    数组变量本身就是特殊的指针

    ●数组变量本身表达地址,所以

    ● int a[10]; int*p=a; //无需用&取地址

    ●但是数组的单元表达的是变量,需要用&取地址

    ●a == &a[0]

    ●[] 运算符可以对数组做,也可以对指针做

    ●p[0] <==> a[0]

    ● *运算符可以对指针做,也可以对数组做

    ● *a=25;

    ● 数组变量是const的指针,所以不能被赋值

    ● int a[] <==> int *const a =

    指针与const

    指针是const(指针指向那个变量,这个事实不能被改变)

    表示一旦得到了某个变量的地址,不能再指向其他变量

    int *const q =&i;   // q是const
    *q = 26;            // OK
    q++;               //ERROR

    所指的是const

    表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)

    const int *p = &i;
    *p=26;         // ERROR! (*p)是const
    i=26;          // OK
    p=&j;          //OK

     

    转换

    ●总是可以把一个非const的值转换成const的

    void f(const  int *x);
    int a = 15;
    f(&a);    //OK
    const int b=a;
    f(&b);      //OK
    b = a+1; //ERROR

    ●当要传递的参数的类型比地址大的时候,这是常用的手段:既要用比较少的字节数传递给参数,又能避免函数对外面的变量的修改

    const数组

    const int a[]={1,2,3,4,5};

    ●数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int 

    ●所以必须通过初始化进行赋值

    指针运算

    ●给一个指针加1表示要让指针指向下一个变量

    int  a[10];
    int *p=a;

    *(p+1)--->a[1]

    ●如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义

    指针计算

    ●给指针加,减一个整数(+,+=,-,-=)

    ●递增递减(++/--)

    ●两个指针相减(地址的差除以sizeof( 类型))

    *p++

    取出p所指的那个数据来,完事之后顺便把p移动到下一个位置去

    ● *的优先级虽然高,但是没有++高

    ●常用于数组类的连续空间操作

    ●在某些CPU上,这可以直接被翻译成一条汇编指令

    char ac[] = {0,1,2,3,4,5,-1};    // -1不是有效数字
    char *p=ac
    while(*p != -1){
    printf("%d
    ",*p++);
    }
    遍历数组ac

    0地址

    ●当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址

    ●所以你的指针不应该具有0值

    ●因此可以用0地址来表示特殊的事情:

    ●返回的指针是无效的

    ●指针没有被真正初始化(先初始化为0)

    ●NULL是一个预定定义的符号,表示0地址

    ●有的编译器不愿意你用0来表示0地址

    指针的类型

    无论指向什么类型,所有的指针的大小都是一样的,因为都是地址

    ●但是指向不同类型的指针是不能直接互相赋值的

    ●这是为了避免用错指针

    指针的类型转换

    ●void* 表示不知道指向什么东西的指针

    ●指针类型亦可以转换类型

    ●int *p = &i;   void*q = (void*)p;

    ●这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量

    ●我不再当你是int啦,我认为你就是一个void!

    用指针来做什么

    ●需要传入较大的数据时用作参数

    ●传入数组后对数组做操作

    ●函数返回不止一个结果

    ●需要用函数修改不止一个变量

    ●动态申请内存时

    malloc

    #include<stdlib.h>

    ●向malloc申请的空间的大小都是以字节为单位的

    ●返回的结果是void*,需要类型为自己需要的类型

    ●(int*)malloc(n*sizeof(int))

    #include <stdio.h>
    #include <stdlib.h>
    int main(void)
    {
        int number;
        int *a;
        printf("输入数量");
        scanf("%d",&number);
         a=(int*)malloc(number*sizeof(int));
        for (i=0;i<number;i++){
            a[i]=i*i;
        }
    free(a);
    return 0; }

    没空间了?

    ●如果申请失败则返回0,或者叫做NULL

    void *p=0;
     int cnt=0;
    while((p=malloc(1024*1024*1024))){
    cnt++;
    free(p)
    printf("分配了%d00MB的空间
    ",cnt);

     

     free()

    ●把申请得来的空间还给系统

    ●申请过来的空间,最终都要还

    ●混出来的,迟早都要还的

    ●只能还申请的空间的首地址

  • 相关阅读:
    从Android源码修改cpu信息
    lintcode-->翻转字符串
    lintcode-->哈希函数
    PCP架构设计
    PCP项目立项
    linux下wc功能的简单实现
    goahead3.6.3就基本使用(后台上传信息到html页面),高手请忽略
    四则运算生成器
    快速看完软件工程教材后,我的疑惑
    软件工程学习
  • 原文地址:https://www.cnblogs.com/zhuxuan1997/p/9396430.html
Copyright © 2011-2022 走看看