zoukankan      html  css  js  c++  java
  • C语言中的函数与指针

    1. 为什么需要函数?

    函数就是功能的封装。

    函数就是为了实现某个功能而编写的一段代码

    scanf()    ,  printf()

    2.函数优点:

    代码更简洁

    代码复用

    如果业务逻辑变化,只把相应的函数修改一下就可以

    3. 怎么定义一个函数

    void start () {

    ….

    }

    函数名就是函数在代码段中的入口地址

    4. 函数调用

    通过函数名调用一个函数,程序执行到这儿后,就会跳转到函数的内部去执行

    5. 函数的分类:库函数和自定义函数

    6. 函数参数,

    在定义函数时声明的参数为形参,在调用函数时的参数为实参。

    实参和形参是两个独立的变量,在函数中对形参所做的修改不影响实参。

    7.在函数中,可以通过return语句结束函数的执行,也可以通过return语句返回一个值

    8.函数的递归调用,

    在函数内部又调用函数它本身

    指针

    int a, b, c;

    scanf(“%d%d%d”, &a, &b, &c);

    printf(“a=%d, b=%d, c=%d ”, a, b, c);

    printf(“&a = %p, &b=%p, &c=%p ”, &a, &b, &c);

    0x33332222 是一个地址

    通过变量名访问该存储空间

    定义变量后,可能是编译器,也可能是操作系统,会把变量名和地址的对应关系保存到内存分配表中

    内存的每个字节单元都有一个数字编号,称为地址

      占8个字节

    内存分配表

    int * p = &a;

    保存地址的变量称为指针变量, p就是一个指针变量,它指向a变量, int * 是数据类型

    p = &b;

    printf(“%ld, %ld, %ld ” , sizeof(p), sizeof(int *) , sizeof(*p));

    scanf(“%d”, a);  //error, 需要指定数据类型int *, 而不是int

    printf(“%lu”, pa) ; //pa变量中的内容按10进制输出 

    printf(“%p”, pa) ; //pa变量中的内容按地址(十六进制)输出

    int *pa = &a;

    char *pc = &c;

    ?? pa多少字节, pc多少字节

    MAC ,iphone 5S后是64位,地址占8字节, iPhone 5s之前的手机是32位的,地址占4个字节

    所以指针变量保存的就是地址,其大小与地址一样大,占8字节或4字节

    二、 *p 是什么

    int a = 10;

    int *pa = &a;

    // &a, &取地址操作,表示到a的地址, pa指向a变量

    // *pa, *取值操作,找到pa所标记的地址单元进行取值

    // *&a == a

    *pa = 20;

    printf(“%d ”, *pa);

    printf(“%d ”, a);

    练习:声明整型变量a,存储数字5,定义一个指针变量指向a,通过指针变量修改a变量的值。

    三、为什么使用指针?

    两个数的交换swap()函数

    void swap( int x , int y) {

      int t = x;

    x = y;

    y = t;

    }

    swap(a, b);

    //在swap函数中交换了x和y, 并不影响实参a和b,是形参和实参是两个独立的变量。

    指针就是为了访问不在当前栈(堆)里的数据

    void swap2( int *p , int *q) { //p = &a, q = &b

    int t = *p; // *p == a

    *p = *q; // *q == b

    *q = t;

    }

    swap( &a, &b);

    需要注意的是,这儿并没有修改形参, 形参是p和q ,而不是*p和*q,对形参p和q的修改并不影响实参

    作业:编写函数,交换两个变量的值

    编写函数,求三个变量的最大值,在函数中将变量的值清0

    编写函数,修改变量的值,将变量的值改为原来值的三次方

    scanf(“%d”, &a);  实际上就是在scanf函数中修改变量a的值,所以要用指针,传递一个地址

    四、指针与数组

    1. 指针加1

    int a = 10;

    int *p = &a;

    printf(“%p ”, p);

    printf(“%p ”, p+1 ); //指针加1,相当于在原来地址的基础上加一个(int )的长度,或者说加一个(*p)的长度 

    例:

    int a = 10, b = 20;

        int *pb = &b;

        printf("%d ", *pb); //20

        printf("%d ", *(pb +1)); //10

    2. 指针与数组

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

    int *p = &arr[0]; //p指向第0个元素

    printf(“%d ”, *(p+1));

    //输出2, p+1表示指向下一个数组元素, *(p+1) 就相当于arr[1]

    数组名就是数组的首地址,即 arr == &arr[0],访问数组的某个元素arr[3]时,就是通过数组的首地址的基础上,进行加3访问这个元素

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

    int *p = a;

    p+1 指向arr2[1]这个元素, *(p+1)就是arr2[1]

    a+2指向arr2[2]这个元素, *(a+2)就是arr2[2]

    同样

    arr2[3]是索引值3的元素

    p[3] == arr2[3];  //是等价的

    需要注意的是:

    p++; //正确,相当于p = p+1

    a++; //错误,因为a数组名不能修改

    3. 数组参数

    数组参数本质上就是一个指针

    如:编写一个函数打印数组的各元素

    void printArr( int *p ,int  length) {

    for ( int i = 0; i < length; i++) {

    printf(“%d ”, p[i] ) ;

    }

    printf(“ ”);

    p[2] = 110; //在这儿修改会影响到主调函数的数组

    }

    int arr[5] = {32,54,55,65,76};

    printArr( arr, 5 );

    printArr( &arr[0], 5);

    printArr( &arr[2], 3);

    练习:编写函数,将任意长整型数组逆序列。

    五.泛型指针和空指针

    1.泛型指针

    void *p; //可以指向任何变量,即可以存储任何变量的地址;

    int a;

    char c;

    int *pa = &a;

    char *pc = &c;

    p = pa;

    p = pc;

    需要注意的是,泛型指针不能取*操作,不能加减操作

    2.空指针:

    如果一个指针不初始化,指针可能指向不可预知的地址单元,这种指针称为野指针。如果使用野指针,可能会产生不可预知的错误

    int *p;

    *p = 123; //危险

    为了防止野 指针,如果创建指针时没有明确的指向,需要将指针设置为空指针

    int * p = NULL;

    六 const关键字

    const修饰变量a,则变量a不能被修改

    const int a = 5; 

    a++; //error, a不能被修改

    const修饰指针变量

    const int *p = &a;

    int const *q = &a;

    q或者q可以指向其他的变量,但是,*p和*q是常量,不能被修改,即:

    *p = 30; 错误

      *(p+1) = 23; //也不对, *p是一个const int常量,则*(p+1)也是一个const int常量

    可以进行强制类型转换如下:

    *(((int *) p) + 1) = 34;

    int * const p = &a;   表示指针变量p是一个常量,不能修改p,即

    p = &b; //错误,

    *p = 444; //正确

    作业:编写函数,求任意长度整形数组的平均数

    编写函数,求任意长度整形数组中第二大的数

    编写函数,传入一个字符串数组,找出最长的英文单词,返回最长单词的起点索引

    编写函数,传入一个字符数组,返回数组中第一个出现的字母,如果没有字母返回0

    编写函数,传入一个字符数组,无需要返回值,将数组中字符压缩打印,如传入helloworld,打印h1e1l3o2w1r1d1

    编写函数,传入两个浮点数和一个字符(+、-、*、/),返回计算结果,如果除数是0,返回-9999

     1. 分析 int a; int * p = &a;

    2. 分析 *p

    3. 分析 p++;

    4. 分析(*p)++;

    5. 分析函数传地址。

    6. 画图分析函数中改变*p,就是改变本体。

    7. 使用指针,写两个相应的函数完成:

      int a, b, c;

    char d, e, f;

    整型求和后,将a,b, c置-1,

    d, e, f 中字符,大小写转换。

    8. 分析int * p = 5;是可以的;int b = &a;也是可以的;int b = &a;int * p = b也是可以的,到底是怎么个过程。

     1.函数实现输入一行字符,另一函数实现分别统计出其中英文字母、空格、数字和其它字符的个数。

    2.函数实现输入一个已经排好序的数组。再输入一个数,要求按原来的规律将它插入数组中。

    3.函数实现将一个数组逆序。(并非逆序输出,是数组本身逆序)

    4.函数实现有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面的m个数

    5.函数实现输入一行字符,最大长度为90,统计出其中有多少个字符串,不算标点。例如:

    输入:Hi, Welcome to Qianfeng!!

    输出:4

    6.编写一个函数,时分秒,输出该时间的下一秒。如输入23时59分59秒,则输出0时0分0秒(**)

    输入格式为    23:59:59

    输出格式为    0:0:0

    7. 编写函数将一个n*n矩阵转置,例如:(****)

      1 2 3 4     1 5 3 4

      5 6 7 8 ->  2 6 2 7  

      3 2 5 9     3 7 5 2

      4 7 2 3     4 8 9 3

    8.函数实现,字符串排序,以main函数参数形式输入9个字符串,然后将字符串按字母顺序进行排序,如果首个字母相同则再比较下一个字母,以此类推。比如:

      "abcdefg", "yusdfsdf", "bsdf", "bjiiig", "zddd",排序后为:

      "abcdefg", "bbjiiig", "bsdf", "yusdfsdf", "zddd"。

  • 相关阅读:
    移动互联网广告
    移动互联网广告
    移动互联网广告
    移动互联网广告
    移动互联网广告
    移动互联网广告
    vue2.0 transition -- demo实践填坑
    纯CSS3制作皮卡丘动画壁纸
    纯CSS3制作卡通场景汽车动画效果
    18种CSS3loading效果完整版
  • 原文地址:https://www.cnblogs.com/ljcgood66/p/5281272.html
Copyright © 2011-2022 走看看