• C/C++指针、函数、结构体、共用体


    指针

    变量与地址

    变量给谁用的?
    变量是对某一块空间的抽象命名。
    变量名就是你抽象出来的某块空间的别名。
    指针就是地址。指向某个地址。

    指针与指针变量

    指针是指向某块地址。指针(地址)是常量。
    指针变量是可以发生变化的。

    指针与指针变量的举例

    #include <stdio.h>
    
    int main()
    {
        int i = 1;
        int *p = &i;
        
        printf("i = %d  \n", i);
        printf("&i = %p \n", &i);
        printf(" p = %p \n", p);
        printf("&p = %p \n", &p);
        printf("*p = %d \n", *p);
    
        // 为什么不用char* p = &i;
        
        //TYPE  NAME = VALUE
        //int*  p    = &i;
        //int   i    = 1;
    
    }
    

    直接访问间接访问

    在这里插入图片描述

    占内存空间

    都是8字节,linux 64 位中。

    空指针 野指针 空类型

    int * i= NULL;
    

    指针运算

    两个指针同时指向一个数组。++ 、--、比较、关系、&、*

    指针与一维数组

    数组名和 指针的区别?
    a是数组名字是一个表示地址的常量。
    指针是一个变量。
    a++;
    p++;
    
    #include <stdio.h>
    
    int main()
    {
        int a[3] = {1,2,3};
        int *p = a;
    
        int i;
        for(i = 0;i < sizeof(a)/sizeof(*a); i++) {
            printf("%d %d %d %d \n",a[i],*(a+i),p[i],*(p+i)); // a[i]
            printf("%p %p %p %p \n",a+i, &a[i],p+i, p+i); // &a[i]
        }
        printf("\n");
    
    }
    

    这里代码体现什么是指针常量什么是指针变量?

    #include <stdio.h>
    
    int main()
    {
        int a[3];
        int i;
        int *p = a;
    
        for(i = 0;i < sizeof(a)/sizeof(*a); i++) {
            printf("%p -> %d\n",&a[i],a[i]);
        }
    
        for(i = 0;i <sizeof(a)/sizeof(*a); i++) {
            scanf("%d",p++);
        }
        //p = a;
        for(i = 0;i < sizeof(a)/sizeof(*a); i++,p++) {
            printf("%p -> %d\n",p,*p);
        }
    
        printf("\n");
    
    }
    

    指针与二维数组

    在这里插入图片描述

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int a[2][3] = {1,2,3,4,5,9};
        int i,j;
        int *p;
    //(W)    p = a; 
        //wall等号右边a是在行间跳转的指针
        // 等号左边是列间跳转的指针
        p = *(a+0);
        //p = &a[0][0];//*(a+0),*a;
    
        printf("%p->%p \n", a, a + 1);
        // printf("%p -> %d \n\n",p,*p);
        
       
    
        // for(i = 0; i < 6; i++,p++) {
        //     printf("%d ",*p);
        // }
        // printf("\n");
    
        for(i = 0;i < 2; i++) {
            for(j = 0; j < 3; j++) {
                printf("%p->%d\n",&a[i][j],a[i][j]);
                printf("%p->%d\n",*(a+i)+j,*(*(a+i)+j));
                //printf("%p->%d\n",a[i]+j,*(*(a+i)+j));
                //printf("%d ",a[i][j]);
            }
            printf("\n");
        }
        exit(0);
    }
    
    

    指针与字符数组

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // 字符指针和字符数组之间的使用
    
    
    // 
    // 练习 定义数组后定义指针 后面操作都用指针实现
    
    int main()
    {
    
    #if 0
        char* str = "hello"; // "hello" 串常量
        printf("%d %d \n",sizeof(str),strlen(str));// 8 5
        //strcpy(str,"world"); //err 为什么不可以?区分字符指针和字符数组的区别  :企图用"world" 覆盖串常量 
        str = "world";
        puts(str);
    #endif 
    
    
    #if 0
        char str[] = "hello";
        printf("%d %d \n",sizeof(str),strlen(str));// 6 5
    
    // (F) str = "hhhh"; // 数组名是一个地址常量怎么可能放到等号左边???
        strcpy(str,"jjjj");
        puts(str);
    
    #endif 
    
    
    
    #if 0
        char str[] = "hello  world";
        char *p = str + 7;
        puts(str);
        puts(p);
    #endif 
    
        exit(0);
    }
    

    const与指针

    #include <stdio.h>
    #include <stdlib.h>
    /*
        常见const 
        const int a;
        int const a;
    
        const int *p; // 常量指针 
        int const *p;
    
        int *const p; // 指针常量
    
        const int *const p;
    
    
        define 不检查语法
    */
    
    int main()
    {
        #if 0
            // cosnt修饰常规变量的使用特点
            // 这个警告已经构成error
            const float pi = 1.14159;
            // pi = 9999.2;
            float *p = &pi; // initialization discards ‘const’ qualifier from pointer target type [enabled by default]
            *p = 1223.333333; 
            // 修改方法 const float *p = &pi; 
    
            printf("%f\n",pi); // 1223.333333
            printf("%f\n",*p);
        #endif
    
    
        // 常量指针:指针的指向可以发生变化但是指针所指向的目标值是不能变化的
        // const  *p
        // 值不能变
        // 指向可以发生变化
        
        int i = 1;
        const int *p1 = &i;
        int j = 88;
    
    //T    i= 10;   
    //F    *p1 = 99;
    //T    p1 = &j;
        printf("%d\n",i);
        printf("%d\n",*p1);
    
    
        // 指针常量:指针的指向不能发生变化,指针所指向的目标变量的值可以发生变化。
        int i = 1;
        int j= 100;
        int * const p1 = &i;
    
    //T    *p1 = 10;
    //F     p1 = &j;
        printf("%d\n",i);
        printf("%d\n",*p1);
    
    
        //const 左右都有 指向和值都不能变
        int num = 10;
        const int* const p3 = &num;
        // *p3 = 99;
        // p3 = &i;
    
    
        exit(0);
    }
    

    指针数组和数组指针的区别

    数组指针

    #include <stdio.h>
    #include <stdlib.h>
    /*
        数组指针: [存储类型] 数据类型 (* 指针名) [下标] = 值;
        int (*p)[3]; -> type name; -> int[3] *p;
    */
    int main()
    {
        // 数组指针
    
        int a[2][3] = {1,2,3,4,5,9};
        int i,j;
        int *p = *a;
        int (*q)[3] = a;
        //printf("%d \n", *a); // a[0][0]的地址
        //printf("%d \n", **a); //1
    
        #if 0
        // printf("%d \n",*p);//q
        //int *p = *a;
        //printf("%d \n",*p); //q
        // int (*q)[3] = a+1;
        // printf("%d \n",**q); // 4
    
    
        printf("\n");
    
    
    
        for(i = 0;i < 2; i++) {
            for(j = 0; j < 3; j++) {
                // printf("%p->%d\n",*(a+i)+j,*(*(a+i)+j));
                printf("%p->%d\n",*(q+i)+j,*(*(q+i)+j));
            }
            printf("\n");
        }
        #endif 
    
    }
    
    

    指针数组:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    /*
        int *arr[3]; -> TYPE NAME; -> int *[3] arr;
    
    */
    int main()
    {
    
        char *name[5] ={"english","math","cpp","teacher","computer"};
    
    
        int i,j;
        for(i = 0; i < 5; i++) {
            puts(name[i]);
        }
        
        for(i = 0; i < 5 ;i++) {
            int k = i;
            for(j = i+1;j < 5; j++) {
                if(strcmp(name[k],name[j]) > 0) {
                    k = j;
                }
            }
            if(k != i) {
                char *tmp = name[i];
                name[i] = name[k];
                name[k] = tmp;
            }
            
        }
        printf("排序后:\n");
        for(i = 0; i < 5; i++) {
            puts(name[i]);
        }
    
        exit(0);
    }
    

    指针和函数

    函数:

    echo $? // 显示上个命令的返回值
    

    在这里插入图片描述

    #include <iostream>
    using namespace std;
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    /*
    
    	定义: 
    	int a[N] = {1,2,3,4,5,6};
    	int *p = a; 
    	
    ->    a     *a    a[0]    &a[3]   p[i]   p     *p   p+1
    ->	  int*	int   int 	  int *	  int    int*  int  int*
      
    */
    //void func1(int *a,int n)
    void func1(int* a,int n,int *b)
    {
    	cout << "== b =" << *b<< endl; // 1
    	for(int i = 0;i < n; i++)
    	{
    		printf("%d ",*(a+i));
    	}
    	printf("\n");
    	
    	return ;
    }
    int main(int argc, char** argv) {
    	int arr[3] = {1,2,3};
    	
    	func1(arr,3,&arr[1]);//&(*(ar+1))
    	
    	
    	return 0;
    }
    

    用指针与一维数组的使用:

    void func2(int *p,int n)
    {
    	int m = n / 2;
    	for(int i = 0;m--;i ++)
    	{
    		int j = n - i -1;
    		int tmp = *(p+i);
    		*(p+i) = *(p+j);
    		*(p+j) = tmp;
    	}
    }
    int main(int argc, char** argv) {
    	int arr[] = {1,2,3,6,4,2,38,4,2,23};
    	
    	//func1(arr,3,&arr[1]);//&(*(ar+1))
    	func2(arr,10);
    	
    	for(int i = 0;i < 10;i ++)
    		cout << arr[i] << ' ' ;
    	cout <<endl;
    	
    	
    	return 0;
    }
    

    函数与二维数组:
    在这里插入图片描述

    #include <iostream>
    using namespace std;
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    /*
    	int a[M][N] = {......};
    	int *p = a;
    	int (*q)[N] = a;
    	
    ->    a[i][j]    *(a+i)       a[i]+j    p[i]        *p
    	  int        int *        int *     int         int
    	  
    ->    q[i][j]    *q           q             p+3         q+2
    	   int       int*         int(*)[N]     int *        int (*)[N]
    	
    */
    
    void func(int *p,int n)
    {
    	
    	for(int i = 0;i < n; i++)
    	{
    		cout << *p << ' ';
    		p++;
    	}
    	
    }
    void print_arr(int (*p)[3])
    {
    	for(int i = 0;i < 3;i++)
    	{
    		for(int j = 0;j < 3;j++)
    		{
    			cout << *(*(p+i)+j) << ' ';
    		}
    		cout<< endl;
    	}
    }
    int main(int argc, char** argv) {
    	int arr[3][3] = {1,2,3,6,4,2,38,4,2};
    	
    	func(arr[0],9); // *arr &arr[0][0]  arr[0]
    	//  这里func(arr,9)  形参是int *p 就报错  p是一个列指针,二维数组不一样 
    	
    	
    	print_arr(arr);
    	
    	
    	return 0;
    }
    

    案例使用二维数组传参

    float average_score(int *a,int n)
    {
    	float sum = 0.0;
    	for(int i = 0;i < n; i++)
    	{
    		sum += *(a+i);
    	}
    	
    	return sum/n;
    }
    void find_num(int(*p)[3],int num)
    {
    	for(int i = 0;i < 3 ;i++)
    		printf("%d ",*(*(p+num) + i));
    	cout << endl;
    	return ;
    }
    int main(int argc, char** argv) {
    	int arr[3][3] = {1,2,3,6,4,2,38,4,2};
    	
    	float ave = 0.0;
    	ave = average_score(*arr,9);
    	printf("%f \n",ave);
    	
    	find_num(arr,0);
    	
    	
    	return 0;
    }
    

    函数与指针关系的详细剖析

    • 指针函数

      • 返回值 * 函数名(参数)
    #if 0
    void find_num(int(*p)[3],int num)
    {
    	for(int i = 0;i < 3 ;i++)
    		printf("%d ",*(*(p+num) + i));
    	cout << endl;
    	return ;
    }
    #else 
    int * find_num(int(*p)[3],int num)
    {
    	return 	*(p+num);
    }
    #endif
    int main(int argc, char** argv) {
    	int arr[3][3] = {1,2,3,6,4,2,38,4,2};
    	
    	float ave = 0.0;
    	ave = average_score(*arr,9);
    	printf("%f \n",ave);
    	
    	int * res;
    	
    	res = find_num(arr,0);
    	if(res != NULL)
    	{
    		for(int i = 0;i < 3;i++)
    			printf("%d ",res[i]);
    		cout <<endl;
    	}
    	else 
    	{
    		printf("can not find\n");
    	}
    	
    	
    	return 0;
    }
    
    • 函数指针
    #include <iostream>
    using namespace std;
    
    int add(int a,int b)
    {
    	return a+b;
    } 
    int sub(int a,int b)
    {
    	return a-b;
    }
    int main(int argc, char** argv) 
    {
    	int a = 2, b = 3;
    	int (*p)(int,int);
    	int (*q)(int,int);
    	
    	int ret;
    	p = add;
    	q = sub;
    		
    	printf("%d \n",p(a,b));
    	printf("%d \n",q(a,b));
    	
    	
    	
    	return 0;
    }
    

    在这里插入图片描述
    回调函数

    • 函数指针数组

      • 类型 (*数组名[下标])(形参);
    #include <iostream>
    using namespace std;
    
    int add(int a,int b)
    {
    	return a+b;
    } 
    int sub(int a,int b)
    {
    	return a-b;
    }
    int main(int argc, char** argv) 
    {
    	int a = 2, b = 3;
    	int (*funcp[2])(int,int);
    	
    	int ret;
    	funcp[0] = add;
    	funcp[1] = sub;
    		
    	for(int i = 0;i < 2; i++)
    	{
    		ret = funcp[i](a,b);
    		printf("%d \n",ret);
    	}
    		
    	return 0;
    }
    
    • 指向指针函数的函数指针数组
      数组存放指针,指针指向函数,函数返回值是指针类型。
      在这里插入图片描述

    结构体

    • 产生的意义
    • 类型描述
    • 嵌套定义
    • 定义变量、初始化及引用
    • 占用内存大小

    定义和使用:

    #include <iostream>
    using namespace std;
    
    
    #define NAMESIZE 100
    
    struct simp_st 
    {
    	int i,j;
    	float f;
    	char ch;	
    };
    
    struct birthday_st
    {
    	int year,month,day;
    };
    
    struct student_st
    {
    	int id;
    	char name[NAMESIZE];
    	struct birthday_st birthday;
    	int math;
    	int chinese;
    };
    
    int main(int argc, char** argv) 
    {
    	
    	struct student_st stu = {10011,"Alan",{3011,22,11},22,54};
    	struct student_st *p = &stu;
    	printf("%d %s %d-%d-%d %d %d \n",stu.id,stu.name,stu.birthday.year,stu.birthday.month,stu.birthday.day,stu.math,stu.chinese);	
    	printf("%d %s %d-%d-%d %d %d \n",p->id,p->name,p->birthday.year,p->birthday.month,p->birthday.day,p->math,p->chinese);
    	
    	
    	struct student_st stu[2] = {{10011,"Alan",{3011,22,11},22,54},{10012,"salay",{2021,2,12},88,66}};
    	struct student_st *p = &stu[0];// &stu[0]  stu
    	for(int i = 0;i < 2;i++,p++)
    	{
    		printf("%d %s %d-%d-%d %d %d \n",p->id,p->name,p->birthday.year,p->birthday.month,p->birthday.day,p->math,p->chinese);
    	}
    	
    	return 0;
    }
    
    • 内存对齐问题
      addr/sizeof()

    构造类型-结构体内存问题及函数传参在这里插入图片描述
    为后面linux高级铺垫。

    • 可以实现一个学生管理系统。

    • 产生及意义
    • 类型描述
    • 嵌套定义
    • 定义变量
    • 占用内存大小
    • 函数传参
    • 位域
    union 名{
    	数据类型 成员名1;
    	数据类型 成员名2;
    };
    
    • 枚举类型
    enum 名{
    	成员1;
    	成员2;
    	成员3;
    }
    
  • 相关阅读:
    MySQL架构优化:定时计划任务与表分区
    关于mysql 删除数据后物理空间未释放(转载)
    Mysql删除数据后磁盘空间未释放的解决办法【转】
    Mysql 自动备份脚本
    迄今最安全的MySQL?细数5.7那些惊艳与鸡肋的新特性(上)【转载】
    Redis学习笔记(二)-key相关命令【转载】
    干货分享:MySQL之化险为夷的【钻石】抢购风暴【转载】
    Apache 实现ProxyPass转发URL到Tomcat并实现http自动转https【转载】
    业务零影响!如何在Online环境中巧用MySQL传统复制技术【转】
    VNC轻松连接远程Linux桌面
  • 原文地址:https://www.cnblogs.com/yaozhenhua/p/15831430.html
Copyright © 2020-2023  润新知