惊落一身雪 发表于 2024-11-23 16:43:37

C语言教程指针笔记整理(一)

https://www.bilibili.com/video/BV1cx4y1d7Ut?spm_id_from=333.788.videopod.episodes&vd_source=e8984989cddeb3ef7b7e9fd89098dbe8&p=107
本篇为贺宏宏老师C语言教程指针部门笔记整理
//.c文件
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
//8-1 什么是指针
//指针:就是地址!
//指针:就是地址!
//指针:就是地址!
int main()
{
    int a = 10; //4个字节   
    int b = 20;

    &a; //获取a的地址
    &b; //获取b的地址

    //printf("a的地址=%p,b的地址=%p\n",&a,&b);//%p:输出地址(指针),以16进制进行输出
    printf("a的地址=%d,b的地址=%d\n",&a,&b);

    return 0;
}
// 8-2 指针变量
int main()
{
    int a = 10;
    int b = 20;
    int *p = &a; //一个int地址(指针)赋值给一个int指针变量
    //获取a的地址,int &p = &a;(int &p C++引用) int *p = &a;
    p = &b; //把b的地址赋值给p //此处不能用*p了,*p的含义是引用,一词多义
    char c;
    double d;
    char *p1 = &c;
    double *p2 = &d;//指针的类型要根据变量的类型进行匹配
    return 0;
}
// 8-3 使用指针变量
int main()
{
    int a = 10;

    printf("%d,%d\n",a,&a);//a的值,a的地址
    int *p = &a;
    printf("%d,%d,%d\n",*p,p,&p);//p指向的变量a的值,a的地址,p的地址

    return 0;
}
// 8-4 &的多个作用
// &的作用:1.按位与 比方4&3 2.取地址 比方 &a 3.C++的引用
//&变量名:获取该变量的地址(指针),&:取地址符(号);这里的&是个单目运算符
//4&3:按位与,这里的&是个双目运算符,有两个变量
int main()
{
    int a = 10;
    int b = 20;
    int c = 4 & 3;//按位与 100 & 011 = 000

    printf("%d\n",c);
    printf("%p,%p,%p\n",&a,&b,&c);
    printf("%p,%p,%p\n",&a&b);//按位与

    int& d = a;//C++的引用,相当于a有一个别名叫d了;与其他两种用法的不同在于这个&前面有数据类型

    return 0;
}
//8-5 指针应用(指针最紧张的部门) Swap互换数据(两个错误示例)
//互换两个变量的值(写成函数)
void Swap_err1(int a, int b)//没有交换成功,错误
{
    int tmp = a;
    a =b;
    b = tmp;
    printf("%d %d",&a,&b);
}

void Swap_err2(int *p1, int *p2)//没有解引用,交换失败
{
    int *tmp = p1;
    p1 = p2;
    p2 = tmp;
}
https://i-blog.csdnimg.cn/direct/523cfb3d107b49ec8e6e7365a71fc10a.png
//8-6 指针应用 Swap互换数据2
//总结:一个函数A通过调用函数B,来修改A中变量的值:
//: 1.必须传指针; 2.B中必须解引用
void Swap(int *p1,int *p2)
{
    int tmp;
    tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

int main()
{
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d %d",&a,&b);
    printf("交换前=%d,%d\n",a,b);

    Swap(&a,&b);//交换a,b两个值

    printf("交换后=%d,%d\n",a,b);
    return 0;
}
https://i-blog.csdnimg.cn/direct/eb40f81123164c1d8241c287c42afa41.png
// 8-7 通过指针返回多个值
//C语言怎么返回两个值?
double Fun(int a, int b, int c)
{
    int d = b * b - 4 * a * c;
    double x1, x2;
    x1 = (-b + sqrt(d))/(2 * a);
    x2 = (-b - sqrt(d))/(2 * a);

    return x1; // C语言一般只能返回0个或1个值
}


double Fun(int a, int b, int c, double *x1,double *x2)
{
    int d = b * b - 4 * a * c;
    double x1, x2;
    *x1 = (-b + sqrt(d))/(2 * a);
    *x2 = (-b - sqrt(d))/(2 * a);

    return 2; //2个根
}

int main()
{
    double x1;
    double x2;
    Fun(4,5,1,&x1,&x2);
    printf("%lf,%lf\n",x1,x2);

}
//8-9 指针指向数组元素
//问题1:指针如何指向这个数组的元素
//问题2:arr名字
//一维数组arr的名字arr表示整个数组只在如下情况:
//1.在界说数组的同一个函数中求sizeof.比方int arr; sizeof(arr) -> 40,由于int是4个字节
//2.在界说数组的同一个函数中&arr+1表示&arr的地址加一整个数组的大小,比方int arr,&arr,&arr+1 = &arr+40
//其他情况,arr都表示数组的起始地址
int main()
{
    int arr = {1,3,5,7,9,11,13,15,17,19};
   
    //int* p = &arr;//第一个元素int的地址
    int *p = arr;//和上一行等价

    printf("%d,\n%d\n",*p,arr);
    printf("%d,\n%d,\n%d\n",&arr,sizeof(arr),&arr+1);

    return 0;
}
//8-10 指针的加法运算
//指针的算数运算:条件是这个指针指向一个数组,同时程序应该包管不越界
//p+整数,p++,++p合法
int main()
{
    int arr = {1,3,5,7,9,11,13,15,17,19};
   
    //int* p = &arr;//第一个元素int的地址
    int *p = arr;//和上一行等价
    printf("%d ",*p);

    //通过指针输出(访问)数组的所有元素
    for(int i = 0; i < 10; i++, p++)
    {
      printf("%d ",*p);
    }
    return 0;
}
//8-11指针的减法运算
//指针的算数运算:条件是这个指针指向一个数组,同时程序应该包管不越界
//p+整数,p++,++p合法
int main()
{
    int arr = {1,3,5,7,9,11,13,15,17,19};
   
    //int* p = &arr;//第一个元素int的地址
    int *p = &arr;//和上一行等价
    int num = sizeof(arr);
    printf("%d\n",num); // sizeof(arr)可是40哦,不是10哦,因为int表示4个字节哦。
    for(int i = 0; i < 10; i++)//所以这里不能写成i < sizeof(arr),这样就循环40次了。超过10就越界,要出错了
    {
      printf("%d ",*p--);
    }
}
//8-12通过指针引用数组元素
int main()
{
    int a;
    int i;
    int *p = a;
    printf("please enter 10 integer numbers:");
    for(i = 0; i < 10; i++)
      scanf("%d", &a);
    for(i = 0; i < 10; i++)
      printf("%d ",a);
    printf("\n");
    return 0;
}
//8-13 指针的关系运算
//<,> >= , <=, !=,条件是必须指向同一个数组,绝对不可以操作差别的数组
// 错误用法:在差别的数组了,返回值为0
int main()
{
    int a = 10;
    int b = 20;
    int *p = &a;
    printf("%d\n",*(p+1));//错误的应用
    int *q = &b;
}
//从头至尾输出数组
int main()
{
    int arr = {1,2,3,4,5,6,7,8,9,10};
   
      for(int *p = arr;p!= &arr;p++)//标准规定可以使用尾后(尾巴的后面:此处是指数组最后一位的下一处地址)地址(指针)
            printf("%d ",*p); //输出1 2 3...
    //或者
    /*
      for(int *p = arr; p != &arr; p++)
            printf("%d ",*p);   
    */

    //或者
    /*
      for(int *p = arr; p <= &arr; p++)
            printf("%d ",*p);   
    */
      return 0;
}
//8-15 指针在数组中的错误应用
//常见的错误:越界错误
int main()
{
    int a;
    int i;
    int *p;
    p= a;
    printf("please enter 10 integer numbers:");
   
    for(i = 0; i < 10; i++)
      scanf("%d", p++); //这里p的指针已经到数组的最后了(p已经到达a的尾后指针),改进办法:p = a;(把p重新赋值),下一行
   
    p = a;
   
    for(i = 0; i < 10; i++,p++)//这里p指针再往后就不是数组内的数了,就是空的地方了,输出的数为随机的数值
      printf("%d ",*p);
    printf("\n");
    return 0;
}
8-16
//8-16 数组作为参数传递:数组名仅仅表示数组首元素的地址
//传数组名+数组长度
//示例1.输出数组的全部元素
//p:数组的起始地址,n:元素的个数
void Show (int *p, int n)
{
    for(int i = 0; i < n; i++)
    {
      printf("%d ",p);
    }
}

int main()
{
    int arr = {1,2,3,4,5,6,7,8,9,10};
    Show(arr,sizeof(arr)/sizeof(arr));//数组元素个数=数组长度/数组每一个元素的长度(这里用第一个元素的长度指代了)
    return 0;
}
//示例2.将数组a中n个整数按相反顺序存放
void inv(int *x, int n) //x数组的起始地址,n元素个数
{
    int tmp;
    //把x当作数组名来操作:(更推荐使用这种方法)
   
    // for(int i = 0, j = n-1; i < j; i++, j--)//i往后走,j往前走
    // {
    //   tmp = x;
    //   x = x;
    //   x = tmp;
    // }
   

    //把x当作指针来操作:
    for(int i = 0, j = n-1; i < j; i++, j--)
    {
      tmp = *(x+i);
      *(x+i) = *(x+j);
      *(x+j) = tmp;
    }   

}

void Show (int *p, int n)
{
    for(int i = 0; i < n; i++)
    {
      printf("%d ",p);
    }
}

int main()
{
    int arr[] = {1,3,5,7,9,11,13,15,17,19};
    inv(arr,sizeof(arr)/sizeof(arr));
    Show(arr,sizeof(arr)/sizeof(arr));
    return 0;
}
把x当作数组名来操作:
https://i-blog.csdnimg.cn/direct/99b62d516c2e4ef3b2c15a13362dacea.png
把x当作指针来操作:
https://i-blog.csdnimg.cn/direct/757dc5b5a8aa425b815510ad0e84271d.png
示例3
https://i-blog.csdnimg.cn/direct/c9c4b873cfef4a1cadfde2a3ea8f4d16.png
5个数字至少必要4次遍历:
第一次:
将第一个数字与剩下的最小值进行比力:
如果第一个数字小于剩下数字的最小值,顺序稳定;
如果第一个数字大于剩下数字的最小值,将剩下数字的最小值与第一个数字进行互换。
第二次:
将第二个数字与剩下的最小值进行比力:
如果第二个数字小于剩下数字的最小值,顺序稳定;
如果第二个数字大于剩下数字的最小值,将剩下数字的最小值与第二个数字进行互换。
第三次:
将第三个数字与剩下的最小值进行比力:
如果第三个数字小于剩下数字的最小值,顺序稳定;
如果第三个数字大于剩下数字的最小值,将剩下数字的最小值与第三个数字进行互换。
第四次:
将第四个数字与剩下的最小值进行比力:
如果第四个数字小于剩下数字的最小值,顺序稳定;
如果第四个数字大于剩下数字的最小值,将剩下数字的最小值与第四个数字进行互换。
第五次:
将第五个数字与剩下的最小值进行比力:
如果第五个数字小于剩下数字的最小值,顺序稳定;
如果第五个数字大于剩下数字的最小值,将剩下数字的最小值与第五个数字进行互换。
//示例3.用指针方法对10个整数按由大到小顺序排序(选择排序法)
//选择法排序:每次从待排序的数中找最小值和待排序的第一个值进行互换,直到全部有序
//arr:数组起始地址,n:元素个数
//下标法。优先保举使用下标法,指针法轻易堕落
void SelectSort1(int* arr, int n)
{
    int k;
    int tmp;
    for(int i = 0; i < n-1; i++)
    {
      k = i;//这里要提前给k赋值一下
      for(int j = i+1; j < n; j++)
      {
            if(arr < arr) //指针方式:*(arr+j) < *(arr+k)
            {
               k = j;
            }
      }
      if(arr != arr)//这里写k!=i就行了
      {
            tmp = arr;//指针方式:*(arr+i)
            arr = arr;//指针方式:*(arr+i) = *(arr+k)
            arr = tmp;//指针方式:*(arr+k)
      }
    }
}
//指针方式:
void SelectSort(int* arr, int n)
{
    int k;
    int tmp;
    for(int i = 0; i < n-1; i++)
    {
      k = i;//这里要提前给k赋值一下
      for(int j = i+1; j < n; j++)
      {
            if(*(arr+j) < *(arr+k))
            {
               k = j;
            }
      }
      if(k != i)
      {
            tmp = *(arr+i);
            *(arr+i) = *(arr+k);
            *(arr+k)= tmp;
      }
    }
}

void Show (int *p, int n)
{
    for(int i = 0; i < n; i++)
    {
      printf("%d ",p);
    }
}

int main()
{
    int arr[] = {10,3,65,7,69,181,193,15,157,19};
    Show(arr,sizeof(arr)/sizeof(arr));
    printf("\n");
    SelectSort(arr,sizeof(arr)/sizeof(arr));
    Show(arr,sizeof(arr)/sizeof(arr));
    return 0;
}

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: C语言教程指针笔记整理(一)