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 再执行++; ++的优先级高于*;












原文地址:https://www.cnblogs.com/litaiqing/p/4615006.html