复制,粘贴,转载,没任何意见,不过还请注明出处,毕竟也是自己的心血~~
作为承上启下的一篇文章,以后以章节命名(可能会以故事的形式出现)
1、承上:HWND,HINSTANCE这些被称作句柄的标识符作用?如何算精通结构体?
我很欣赏黑格尔的一句话,存在即合理。何为柄,最简单的方式就是理解伞柄,100个人撑开100把伞,总共有100个伞柄,每一个伞柄都对应着一把伞,似乎发现了什么?如果我给这100把伞的伞柄都取不同的名字,我可以根据伞柄名字找到对应的伞,句柄的作用的类似与伞柄,伞对应着程序,不同的程序有需要加载不同的文件或资源或改变属性(简单理解,就是从磁盘中获取自己需要的内存内容),句柄就是对这些资源的标识,通过它,你可以找到需要的内存内容,来看一个最简单的例子(开始对上一篇文章内容进行分析咯,个人见解,有好的想法欢迎讨论~~)
HWND hwnd;
hwnd = CreateWindow(szAppName, // window class name
TEXT("我的第一个应用程序"), //window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
HWND 是一个窗口句柄,然后HWND hwnd;就是给一个句柄起一个名字叫做hwnd,hwnd = CreateWindow(...);CreateWindow()这是一个创建窗口函数,内部做了哪些事呢?很简单,就是创建了一个显示窗口所需要的资源内存,现在的句柄有了一个特定的名字,叫做hwnd(当然,名字这玩意,全凭程序员爸爸),且hwnd=CreateWindow(...);从逻辑上可以得知,他们之间一定存在关系(至于是赋值还是其他,这个往后看,就知道了)不管怎么样,现在我可以通过这个玩意获取到我需要的内存内容了。(学习的过程中,肯定会有或多或少的疑问,个人逻辑是先了解作用是什么,再去谈实现或者内部原理,在我的算法文章里会有这种逻辑概念)
问:上面的伞柄例子,为什么给伞柄命名,而不给伞本身命名?我直接使用 CreateWindow(...)不行吗?为什么要 通过一个叫做窗口句柄的东西?
答:为了回答这个问题,现在再看一个例子,能看这些文章的,肯定是有基础的,没基础的请移步我文集里的《零基础学编程》,先看c++中的函数:
上一个例子很简单,创建一个控制台,然后就是输入以上代码
再看这个代码,即使是a或者b,都会有int关键字,说白了,int也是标识符,然后将show1()的内存值赋值给a,细心的发现了,上面说有hwnd=CreateWindow(...);这个是赋值还是其他的问题,如果我的函数返回的是指针,该用什么去接收,
下面看一下这个运行
基于这个,有什么想法没?不管逻辑是什么,接着看:
第一:函数体内的两句话被打印两次,且地址不同;
第二:指针p的地址与第一次a、q的地址相同,show1()的地址值与第二次a、q的地址值相同;
第三:出现的两种地址相差一个int的大小,
基于以上三点,可尝试推论:
推论1:如果把int换成double,你会发现,地址相差一个double的大小
推论2:这两者之间存在某种关系
眼尖的同学发现了,局部变量,还给了一个警告,基于此,推论以及第一,第二,第三都是错误的,想了解的同学请查看,《堆栈的故事》
还有就是以上或以下截图不能运行请添加return 0;//这里这么用做个引子,会讲为什么的
int main(){
//...
return 0;
}
特此说明
句柄的出现,是为了方便保存,就像你用一个变量保存函数的值或者指针一样,(也可以理解为句柄就是指针),这里说一个概念,指针的指针也是指针,嘻嘻~~,不管是指针,还是指针的指针,还是指针的指针的指针,其作用和目的都是获取内存内容,单个的也好,结构体也罢,只是方式上有一定的区别,至于区别在哪里,以后分析,暂时用不到,先了解作用。
问:如何才算精通结构体?
答:不仅会用,还要知道结构体为什么会出现,数组和结构体的关系是什么?一步一步来(为了能让大家更好的明白,所有的都会给出源码,如果是图片,那里面就那么点代码,多的,给链接,或者给百度云)
先看结构体的用法:
从内存方面理解结构体
结论:
1.地址一样,取出的内存值一样
2.student1的地址与student1.age的地址相同(事实上,结构体的实例后的名称地址与第一个成员的地址相同)
3.指针加一偏移都是自身字节数的大小,结构体偏移+1是类成员字节数共大小,当然,这里面又涉及到字节对齐的概念(以后解释),有兴趣的朋友可以自行测试,这里给出我的测试代码,见下方
4.现在可以类比数组名就是元素首地址了把(针对一维数组);二维及以上会单独讲解
5.吃透了结构体,链表随心所欲使用
#include <iostream>
#include<stdio.h>
#include<string>
struct student {
int age;
std::string name;
};
int main()
{
struct student student1;
student1.age = 20;
student1.name = "张飞";
std::cout << "我是student1的age:" << student1.age << std::endl;
std::cout << "我是student1的name:" << student1.name << std::endl;
std::cout << "下面是地址:" << std::endl;
std::cout << "我是student1的地址:" << &student1 << std::endl;
std::cout << "我是student1的age的地址:" << &student1.age << std::endl;
std::cout << "我是student1的name的地址:" << &student1.name << std::endl;
std::cout << "我是student1的地址偏移1个单位:" << &student1 + 1 << std::endl;
std::cout << "我是student1的age的地址偏移1个单位:" << &student1.age + 1 << std::endl;
std::cout << "我是student1的name的地址偏移1个单位:" << &student1.name + 1 << std::endl;
std::cout << "下面是根据地址取值:" << std::endl;
std::cout << "我是student1的地址加*取值:";
printf("%d\n",*(&student1));
std::cout << "我是student1的age的地址加*取值:" << *(&student1.age) << std::endl;
std::cout << sizeof(std::string) << std::endl;
return 0;
}
结构体你还有什么不懂吗?欢迎留言~~
启下 :拿到句柄以后,我们可以做什么,既然是内存值,那么我们是否可以修改??
下一章,小彩蛋,实现句柄的功能使用(简单而又好玩的程序设计)。
厨师真的挺好
2019-4-11