• CPP数据类型本质以及变量本质分析


    1. //避免在.c里面重复包含多次头文件
    2. #ifndef _CLT_SOCKET2_H__
    3. #define _CLT_SOCKET2_H__
    4. //...
    5. #endif
    //因为数据类型不一样



    数据类型的本质:
    数据类型可理解为创建变量的模具(模子),是固定内存大小的别名。
    数据类型的作用:
    编译器预算对象(变量)分配的内存空间大小。
    int a[10] = { 1,5,7,9,3,4,6,8,2,0 }; 
    a 与 &a 数据类型不一样,步长不一样 

    typedef int u32;可以为数据类型起别名。

    数据类型封装1
    1、void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。
    2、用法1:数据类型的封装
        int InitHardEnv(void **handle);
         典型的如内存操作函数memcpy和memset的函数原型分别为
     void * memcpy(void *dest, const void *src, size_t len);
     void * memset ( void * buffer, int c, size_t num );  
    3、用法2:  void修饰函数返回值和参数,仅表示无。
            如果函数没有返回值,那么应该将其声明为void型
           如果函数没有参数,应该声明其参数为void
           int function(void)
          {return 1;}
    4、void指针的意义 就是把一个不知道数据类型的地址传递过去
          C语言规定只有相同类型的指针才可以相互赋值
          void*指针作为左值用于“接收”任意类型的指针
          void*指针作为右值赋值给其它指针时需要强制类型转换
          int *p1 = NULL;
          Char *p2 = (char *)malloc(sizoeof(char)*20); 
    5、不存在void类型的变量
          C语言没有定义void究竟是多大内存的别名
    6、扩展阅读《void类型详解.doc》


    变量   本质是什么?(一段连续)内存空间的别名,变量是一个标号
    概念:既能读又能写的内存对象,称为变量;若一旦初始化后不能修改的对象则称为常量。
     变量定义形式:     类型  标识符, 标识符, … , 标识符 ; 
    变量本质:(一段连续)内存空间的别名
    1、程序通过变量来申请和命名内存空间 int a = 0
    2、通过变量名访问内存空间

    修改变量有几种方法?
    1、直接
    2、间接。内存有地址编号,拿到地址编号也可以修改内存;于是指针横空出世了!
    3、内存空间可以再取给别名吗?可以取别名,比如C++的引用,引用的本质就是给变量起了个别名,引用和变量的本质不同。

    程序的内存四区模型

    1. void main(){
    2. int a = 10; //分配4个字节的内存在栈区,栈区也叫临时区
    3. int *p ;//分配4个字节的内存
    4. p = &a; //CPU执行的代码,放在代码区
    5. *p = 20;//
    6. {
    7. char *p =NULL;//分配4个字节的内存
    8. p = (char *)malloc(100);
    9. if(p != NULL){
    10. free(p);
    11. }
    12. }
    13. system("pause");
    14. }
    流程说明
    1、操作系统把物理硬盘代码load到内存
    2、操作系统把c代码分成四个区
    3、操作系统找到main函数入口执行

    内存四区模型-各个元素分析


    指针变量和它所指向的内存空间变量是两个不同的概念
    指针指向谁,就把谁的地址赋给指针。


    内存四区概念

    函数1调用函数2,函数1称为主调函数 函数2称为被调用函数

    规则1Main(主调函数)分配的内存(在堆区,栈区、全局区)都可以在被调用函数里使用吧。

    规则2:在被调用函数里面分配的内存

    1、如果在被调用函数里面的临时区(栈)分配内存,主调用函数是不能使用的。

    char * getstring3()

    {

    char buf[30];

    strcpy(buf, "abcde");

    return buf;

    }


    如何建立正确的程序运行内存布局图
    内存四区模型&函数调用模型
    函数内元素 
    深入理解数据类型和变量“内存”属性
    一级指针内存布局图(int *,char*)
    二级指针内存布局图(int ** char **)
    函数间接
    主调函数分配内存,还是被调用函数分配内存
    主调函数如何使用被调用函数分配的内存(技术关键点:指针做函数参数)

    栈的模型生态是开口向下的。堆的模型生态是开口向上。
    Heap、Stack生长方向和内存存放方向是两个不同概念。

    *p 解释: *就像一把钥匙,根据一个指针变量的值,去修改门后面的内存空间。

    指针变量和它指向的内存块是两个不同的概念
    //含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++
    //含义2 给*p赋值*p='a'; 不会改变指针变量的值,只会改变所指的内存块的值  
    //含义3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结!
    //含义4 =左边char *p 
    //含义5 保证所指的内存块能修改

    指针也是一种数据类型,占4个字节
    1. #include "stdio.h"
    2. #include "stdlib.h"
    3. //char *p1 形参 形参也是被调用该函数的参数,只不过具有对外属性而已。
    4. //
    5. void getData01(char *p1)
    6. {
    7. printf("getData01() begin ");
    8. return ;
    9. }
    10. ////char *p1 形参 是变量
    11. void getData02(char **p2)
    12. {
    13. printf("getData01() begin ");
    14. return ;
    15. }
    16. ////char *p1 形参 是变量
    17. void getData03(char **p3)
    18. {
    19. printf("getData01() begin ");
    20. return ;
    21. }
    22. ////char *p7 形参 是变量
    23. void getData07(char *******p7)
    24. {
    25. printf("getData01() begin ");
    26. return ;
    27. }
    28. /*
    29. //对参数的指针类型应该怎么理解
    30. //理解角度需要从两个角度出发
    31. //站在c/c++编译器的角度 对形参,如果是指针类型,c编译器只会分配四个字节的内存。
    32. ////char *p7 形参 是变量
    33. //指针的数据类型到底是什么
    34. 指针的数据类型是指它所指向的内存空间的数据类型

    35. 指针的数据类型具有依附特性

    36. 结论:指针的步长,根据所指内存空间类型来定。
    37. void senddata01(char *p1); void senddata01(char* p1);
    38. void senddata02(char ** p1); void senddata02(char * *p1); void senddata02(char **p1);
    39. void senddata03(char ***p1);
    40. void senddata04(char *p[]); void senddata04(char * p[]); void senddata04(char *p []);
    41. void senddata05(char (*p)[10]); void senddata05(char (*p) [10]);
    42. void senddata05(char *****p4);
    43. */
    44. void main61()
    45. {
    46. char *p1 = NULL;
    47. char **p2 = NULL;
    48. int a = 10;
    49. int *p3 = NULL;
    50. int c = 0;
    51. a = 20; //直接通过变量修改a的值
    52. p3 = &a; //
    53. //*p放在=号的左边,去修改内存空间的值。
    54. *p3 = 30; //通过指针间接修改内存空间的值
    55. c = *p3; //*p放在等号的右边从内存空间中拿值
    56. /*
    57. while(*p != ''')
    58. *p1++ = *p2++
    59. */
    60. //*p 的意义:*就像一把钥匙,根据一个指针变量的值,去修改门后门的内存空间
    61. {
    62. char *p2 = 0x0077;
    63. *p2 = 100;
    64. *((int *)77) = 100;
    65. }
    66. printf("p2:%d ", sizeof(p2));
    67. system("pause");
    68. }
    69. void main63()
    70. {
    71. char *p1 = NULL;
    72. char *p2 = NULL;
    73. char buf1[100] = {0};
    74. char buf2[100] = {0};
    75. strcpy(buf1, "abcdefg");
    76. p1 = buf1;
    77. p2 = buf2;
    78. while(*p1 != '')
    79. {
    80. *p2 = *p1;
    81. p2++; //p2 向后跳动1个字节
    82. p1++;
    83. }
    84. }
    85. void main()
    86. {
    87. // {
    88. // char *p = NULL;
    89. // *p = 100;
    90. //
    91. // }
    92. // {
    93. // char *p = 0x77;
    94. // *p = 100;
    95. //
    96. // }
    97. {
    98. char *p = "abcdefg";
    99. p = 100;
    100. printf("%x ", p);
    101. *p = 'z';
    102. }
    103. system("pause");
    104. }

    //10 字面量,放在不能取地址 没有放在堆栈、全局区,可以按照放在代码区域之类的区域内理解它。
    int *a = &10;
    指针是一种数据类型,是指它指向的内存空间的数据类型。
    含义1:指针步长(p++),根据所指内存空间的数据类型来确定。
    p++ =   -->> (unsigned char)p+sizeof(a);
    结论:指针的步长,根据所指内存空间类型来定、



    通过*p/*p++来改变变量的值是指针存在的最大意义
    1)两码事:指针变量和它指向的内存块的变量
    2)条件反射:指针指向某个变量,就是把某个变
    量地址赋给指针
    3)*p间接赋值成立条件:3个条件
        1,2个变量(通常一个实参,一个形参)
        2,建立关系,实参取地址赋给形参指针
        3,*p形参,求间接的修改实参 的值
    1.2.3是指,上述,1,2,3个条件


    1. #include "stdio.h"
    2. #include "stdlib.h"
    3. #include "string.h"
    4. //指针做函数参数
    5. //函数调用过程中,
    6. //用1级指针(通常是形参,)去修改0级指针(通常是实参)的值
    7. //用2级指针(通常是形参,)去修改1级指针(通常是实参)的值
    8. //用3级指针(通常是形参,)去修改2级指针(通常是实参)的值
    9. //用8级指针(通常是形参,)去修改7级指针(通常是实参)的值
    10. //用n级指针(通常是形参,)去修改n-1级指针(通常是实参)的值
    11. int getLen(int *p) {
    12. *p = 40; //形参通过地址间接的修改实参的值
    13. return 0;
    14. }
    15. /*
    16. 间接赋值的应用场景有2个
    17. 1.在函数之内 *p1++ = *p2++
    18. 2.指针做函数参数,通过*p形参去间接的修改实参的值,这才是指针存在的最大意义
    19. 这才是C语言特有的现象,才是指针的精华。
    20. */
    21. void main() {
    22. int a = 10; //定义了一个变量(实参)
    23. int *p = NULL; //定义了一个变量 (形参)
    24. a = 20; //直接修改a的值
    25. printf("a: %d ", a);
    26. p = &a;//把a的地址赋给p //把一个变量的地址传递给另外一个变量 //实参取地址传给形参
    27. *p = 30;//间接赋值,如果p是a的地址,那么就间接的修改a的值 //*p放在等号的左边
    28. printf("a: %d " ,a );
    29. //p = &a; //a的地址赋给p,把这句话,转成函数调用
    30. getLen(&a);
    31. printf("a: %d ", a);
    32. system("pause");
    33. }
    //[] *
    //[] -----> *
    //buf[i] --> bur[0+i]  ---> *(p+1) -->p[i]
    //站在C++编译器的角度,*p相当于我们程序猿手工(显示)利用间接赋值,去操作内存
    //[]怎么理解?只不过是C++编译器帮我们程序猿做了*p操作

    *to++ = *from++;先执行*to 再执行++; ++的优先级高于*;












  • 相关阅读:
    leetcode 7:binary-tree-preorder-traversal
    leetcode 49:same-tree
    leetcode 45:maximum-depth-of-binary-tree
    leetcode 15:single number
    leetcode开始刷题!
    MFC按行读写文件,亲测有用!
    把字符串转换成整数
    数组中重复的数字
    CSS盒子模型图
    HTML5入门:HTML5的文档声明和基本代码
  • 原文地址:https://www.cnblogs.com/litaiqing/p/4615006.html
Copyright © 2020-2023  润新知