CPP数据类型本质以及变量本质分析
//避免在.c里面重复包含多次头文件#ifndef _CLT_SOCKET2_H__#define _CLT_SOCKET2_H__- //...
#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++的引用,引用的本质就是给变量起了个别名,引用和变量的本质不同。
程序的内存四区模型

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

指针变量和它所指向的内存空间变量是两个不同的概念
指针指向谁,就把谁的地址赋给指针。
内存四区概念
函数1调用函数2,函数1称为主调函数 函数2称为被调用函数 |
规则1:Main(主调函数)分配的内存(在堆区,栈区、全局区)都可以在被调用函数里使用吧。 |
规则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个字节
#include "stdio.h"#include "stdlib.h"//char *p1 形参 形参也是被调用该函数的参数,只不过具有对外属性而已。//void getData01(char *p1){printf("getData01() begin\n");return ;}////char *p1 形参 是变量void getData02(char **p2){printf("getData01() begin\n");return ;}////char *p1 形参 是变量void getData03(char **p3){printf("getData01() begin\n");return ;}////char *p7 形参 是变量void getData07(char *******p7){printf("getData01() begin\n");return ;}/*//对参数的指针类型应该怎么理解//理解角度需要从两个角度出发//站在c/c++编译器的角度 对形参,如果是指针类型,c编译器只会分配四个字节的内存。////char *p7 形参 是变量//指针的数据类型到底是什么指针的数据类型是指它所指向的内存空间的数据类型指针的数据类型具有依附特性结论:指针的步长,根据所指内存空间类型来定。void senddata01(char *p1); void senddata01(char* p1);void senddata02(char ** p1); void senddata02(char * *p1); void senddata02(char **p1);void senddata03(char ***p1);void senddata04(char *p[]); void senddata04(char * p[]); void senddata04(char *p []);void senddata05(char (*p)[10]); void senddata05(char (*p) [10]);void senddata05(char *****p4);*/void main61(){char *p1 = NULL;char **p2 = NULL;int a = 10;int *p3 = NULL;int c = 0;a = 20; //直接通过变量修改a的值p3 = &a; ////*p放在=号的左边,去修改内存空间的值。*p3 = 30; //通过指针间接修改内存空间的值c = *p3; //*p放在等号的右边从内存空间中拿值/*while(*p != '\0'')*p1++ = *p2++*///*p 的意义:*就像一把钥匙,根据一个指针变量的值,去修改门后门的内存空间{char *p2 = 0x0077;*p2 = 100;*((int *)77) = 100;}printf("p2:%d\n", sizeof(p2));system("pause");}void main63(){char *p1 = NULL;char *p2 = NULL;char buf1[100] = {0};char buf2[100] = {0};strcpy(buf1, "abcdefg");p1 = buf1;p2 = buf2;while(*p1 != '\0'){*p2 = *p1;p2++; //p2 向后跳动1个字节p1++;}}void main(){// {// char *p = NULL;// *p = 100;//// }// {// char *p = 0x77;// *p = 100;//// }{char *p = "abcdefg";p = 100;printf("%x \n", p);*p = 'z';}system("pause");}
//10 字面量,放在不能取地址 没有放在堆栈、全局区,可以按照放在代码区域之类的区域内理解它。
int *a = &10;
指针是一种数据类型,是指它指向的内存空间的数据类型。
含义1:指针步长(p++),根据所指内存空间的数据类型来确定。
p++ = -->> (unsigned char)p+sizeof(a);
结论:指针的步长,根据所指内存空间类型来定、
通过*p/*p++来改变变量的值是指针存在的最大意义
1)两码事:指针变量和它指向的内存块的变量
2)条件反射:指针指向某个变量,就是把某个变量地址赋给指针
2)条件反射:指针指向某个变量,就是把某个变量地址赋给指针
3)*p间接赋值成立条件:3个条件
1,2个变量(通常一个实参,一个形参)
2,建立关系,实参取地址赋给形参指针
3,*p形参,求间接的修改实参 的值
1.2.3是指,上述,1,2,3个条件
#include "stdio.h"#include "stdlib.h"#include "string.h"//指针做函数参数- //函数调用过程中,
- //用1级指针(通常是形参,)去修改0级指针(通常是实参)的值
- //用2级指针(通常是形参,)去修改1级指针(通常是实参)的值
- //用3级指针(通常是形参,)去修改2级指针(通常是实参)的值
- //用8级指针(通常是形参,)去修改7级指针(通常是实参)的值
- //用n级指针(通常是形参,)去修改n-1级指针(通常是实参)的值
int getLen(int *p) {*p = 40; //形参通过地址间接的修改实参的值return 0;}/*间接赋值的应用场景有2个1.在函数之内 *p1++ = *p2++2.指针做函数参数,通过*p形参去间接的修改实参的值,这才是指针存在的最大意义这才是C语言特有的现象,才是指针的精华。*/void main() {int a = 10; //定义了一个变量(实参)int *p = NULL; //定义了一个变量 (形参)a = 20; //直接修改a的值printf("a: %d \n", a);p = &a;//把a的地址赋给p //把一个变量的地址传递给另外一个变量 //实参取地址传给形参*p = 30;//间接赋值,如果p是a的地址,那么就间接的修改a的值 //*p放在等号的左边printf("a: %d \n" ,a );//p = &a; //a的地址赋给p,把这句话,转成函数调用getLen(&a);printf("a: %d \n", a);system("pause");}
//[] *
//[] -----> *
//buf[i] --> bur[0+i] ---> *(p+1) -->p[i]
//站在C++编译器的角度,*p相当于我们程序猿手工(显示)利用间接赋值,去操作内存
//[]怎么理解?只不过是C++编译器帮我们程序猿做了*p操作
*to++ = *from++;先执行*to 再执行++; ++的优先级高于*;

浙公网安备 33010602011771号