函数指针

CString, BSTR, LPCTSTR 概念

纵饮孤独 提交于 2019-12-03 13:21:59
CString是一个动态TCHAR数组 , BSTR是一种专有格式的字符串(需要用系统提供的函数来操纵 ) LPCTSTR只是一个常量的TCHAR指针。 CString 是一个完全独立的类,动态的TCHAR数组,封装了+等操作符和字符串操作方法。 typedef OLECHAR FAR* BSTR; typedef const char * LPCTSTR; vc++中各种字符串的表示法 首先char* 是指向ANSI字符数组的指针,其中每个字符占据8位(有效数据是除掉最高位的其他7位),这里保持了与传统的C,C++的兼容。 LP的含义是长指针(long pointer)。LPSTR是一个指向以‘\0’结尾的ANSI字符数组的指针,与char*可以互换使用,在win32中较多地使用LPSTR。而LPCSTR中增加的‘C’的含义是“CONSTANT”(常量),表明这种数据类型的实例不能被使用它的API函数改变,除此之外,它与LPSTR是等同的。 1. LP表示长指针,在win16下有长指针(LP)和短指针(P)的区别,而在win32下是没有区别的,都是32位.所以这里的LP和P是等价的. 2. C表示const 3. T是TCHAR,在采用Unicode方式编译时是wchar_t,在普通时编译成char. 为了满足程序代码国际化的需要,业界推出了Unicode标准

go map数据结构和源码详解

白昼怎懂夜的黑 提交于 2019-12-03 10:26:23
目录 1. 前言 2. go map的数据结构 2.1 核心结体体 2.2 数据结构图 3. go map的常用操作 3.1 创建 3.2 插入或更新 3.3 删除 3.4 查找 3.5 range迭代 3.5.1 初始化迭代器mapiterinit() 3.5.2 迭代过程mapiternext() 4. go map的扩容缩容 4.1 扩容缩容的基本原理 4.2 为什么叫“伪缩容”?如何实现“真缩容”? 5 Q&A关键知识点 5.1 基本原理 5.2 时间复杂度和空间复杂度分析 1. 前言 本文以go1.12.5版本分析,map相关的源码在runtime包的map开头的几个文件中,主要为map.go。 go的map底层实现方式是hash表(C++的map是红黑树实现,而C++ 11新增的unordered_map则与go的map类似,都是hash实现)。go map的数据被置入一个由桶组成的有序数组中,每个桶最多可以存放8个key/value对。key的hash值(32位)的低阶位用于在该数组中定位到桶,而高8位则用于在桶中区分key/value对。 go map的hash表中的基本单位是桶,每个桶最多存8个键值对,超了,则会链接到额外的溢出桶。所以go map是基本数据结构是hash数组+桶内的key-value数组+溢出的桶链表 当hash表超过阈值需要扩容增长时

go map数据结构和源码详解

别说谁变了你拦得住时间么 提交于 2019-12-03 07:58:52
目录 1. 前言 2. go map的数据结构 2.1 核心结体体 2.2 数据结构图 3. go map的常用操作 3.1 创建 3.2 插入或更新 3.3 删除 3.4 查找 3.5 range迭代 3.5.1 初始化迭代器mapiterinit() 3.5.2 迭代过程mapiternext() 4. go map的扩容缩容 4.1 扩容缩容的基本原理 4.2 为什么叫“伪缩容”?如何实现“真缩容”? 5 Q&A关键知识点 5.1 基本原理 5.2 时间复杂度和空间复杂度分析 1. 前言 本文以go1.12.5版本分析,map相关的源码在runtime包的map开头的几个文件中,主要为map.go。 go的map底层实现方式是hash表(C++的map是红黑树实现,而C++ 11新增的unordered_map则与go的map类似,都是hash实现)。go map的数据被置入一个由桶组成的有序数组中,每个桶最多可以存放8个key/value对。key的hash值(32位)的低阶位用于在该数组中定位到桶,而高8位则用于在桶中区分key/value对。 go map的hash表中的基本单位是桶,每个桶最多存8个键值对,超了,则会链接到额外的溢出桶。所以go map是基本数据结构是hash数组+桶内的key-value数组+溢出的桶链表 当hash表超过阈值需要扩容增长时

最基础的数据结构-左轻侯

一曲冷凌霜 提交于 2019-12-03 06:07:53
作者:左轻侯 创建时间:2007-03-04 22:29:06 最后修改时间:2008-01-18 22:07:52 本文发表于《程序员》2007年第3期      最基础的数据结构   左轻侯   2007.2.3      引言       任何一个受过专业训练的程序员,对“数据结构”这门课程中涉及到的各种数据结构都不会感到陌生。但是,在实际的编程工作中,大部分的数据结构都不会用到,而且也许永远都不会用到。造成这种现象的原因有二:一是根据80/20法则,常用的数据结构只会占到少部分;二是计算机语言往往已经对常用的数据结构进行了良好的封装,程序员不需要关心内部的实现。    虽然如此,深入地理解基本数据结构的概念和实现细节,仍然是每一个程序员的任务。这不仅是因为,掌握这些知识,将有利于更加正确和灵活地应用它们,而且也是因为,对于语言背后的实现细节的求知欲,是一个优秀的程序员的素质。    本文将讨论实际编程最经常使用的三种数据结构:字符串、数组和Hash表,比较它们在不同语言中的实现思路,并涉及它们的使用技巧。      字符串    严格地说,字符串(string)甚至不能算作一种单独的数据结构,至少在C语言中,它仅仅是某种特定类型的数组而已。但是,字符串在实际使用中是如此重要,在不同语言中的实现又差异颇大,因此,它值得被作为一种抽象数据类型单独进行讨论

C语言qsort函数总结

一个人想着一个人 提交于 2019-12-03 05:25:08
   前几天在leetcode上刷题,用qsort对二维数组进行排序,发现不会写qsort的比较函数。后面在网上找了几篇博客才弄明白,趁今天有空,对这个做一下总结,主要是以下4个方面: 1、qsort总体介绍 2、qsort应用于一维数组 3、qsort应用于指针数组 4、qsort应用于二维数组 1、qsort总体介绍   函数声明:void qsort(void *base, size_t nitems, size_t size, int (*compare)(const void *, const void*))   参数解释:     base-- 指向要排序的 数组 的第一个元素的指针。注意这里说是数组,所以必须是对连续的内存块进行排序。     nitems-- 由 base 指向的数组中元素的个数     size-- 数组中每个元素的大小,以字节为单位     compare-- 用来比较两个元素的函数。这是qsort最难的一部分了。这里主要要注意以下2点:1、在写compare函数时,你的两个形参必须是const void *型,但是在compare函数内部你又必须将const void *类型的形参转换为实际的类型。这是我最当时最难以理解的一个问题了:我需要转换成什么类型。看了别人的总结才知道,是: 指向数组元素的指针,指向数组元素的指针,指向数组元素的指针

iphone 面试题(转)

廉价感情. 提交于 2019-12-03 04:51:19
转】 iPhone 面试题解答 2011-07-20 0:51 转载自 492437598 最终编辑 492437598 1.main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); } 答:2,5 *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5   &a+1不是首地址+1,系统会认为加一个a数组的偏 移,是偏移了一个数组的大小(本例是5个int)   int *ptr=(int *)(&a+1);   则ptr实际 是&(a[5]),也就是a+5 原因如下:   &a是数组指针,其类型为 int (*)[5];   而 指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同。   a是长度为5的int数组指针,所以要加 5*sizeof(int)   所以ptr实际是a[5]   但是prt与(&a+1)类型是不一样的(这点很重要)    所以prt-1只会减去sizeof(int*)   a,&a的地址是一样的,但意思不一样 a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址, a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]. 2. 以下为Windows NT下的32位C+

通过导出表找导出函数

梦想与她 提交于 2019-12-03 03:57:46
例如:一个HelloDll.dll 其导出表信息如下: 该dll有4个函数; 用.def的方式导出; 其中有个匿名函数; 1.分析 导入dll中的函数有两种方式: 1】通过序号 2】通过函数名 例如:显式链接dll时使用的库函数“GetProcAddress”实现了用函数的查找; myPlus = (lpPlus)GetProcAddress(hModule, "_Plus@8"); 其中的参数hModule实际上是pe文件拉伸后的起始位置ImageBase; 2.通过函数名导入 思路: 遍历名字表,获取函数名,与目标函数名比对,如果有相同的函数名,获得该函数名在名字表中的索引; 注意:名字表中储存的是函数名的内存镜像中相对ImageBase的偏移地址,需要转换成文件镜像偏移地址; 用获得的索引在序号表中找到该函数对应的序号; 以序号为索引在函数地址表中找到函数的地址; 注意:函数地址表中储存的是函数内存镜像的偏移地址,需要转换为文件镜像的偏移地址; 用函数指针接收函数的地址; 使用函数; 函数: GetFunctionAddrByName(FileBuffer指针,函数名指针) 代码: #include "stdafx.h" #include "PeTool.h" #include "string.h" #define SRC "C:\\Users\\Administrator\

async await 的原理

匿名 (未验证) 提交于 2019-12-03 00:40:02
在公司的项目中,我们经常用到async await 这样的函数,它的作用也很奇特,可以让异步的函数等待异步执行的结果出来再继续往下进行。我一直很好奇这是怎么做到的,它内部的机理是怎么样的,就一个关键词在函数前面加async,在异步操作前面加await就可以做到。他是怎么做到的呢? 现在我们用的vue项目就会把我们的语法打包编辑成浏览器可以识别的语句,那么async,await 是从什么地方出来的呢,他是怎么实现异步变同步的呢? 我们的异步操作async await 如果错了就不会继续执行,如果我想让他继续执行应该怎么做? try cache? 还有呢? 为什么可以呢?内部是怎么执行的呢? function Fun () { return new Promise((resolve,reject) => { setTimeout(reject( new Error ( '你错了' )), 3000 ); }) } function Fun2 () { return new Promise((resolve) => { setTimeout(resolve, 3000 ); }) } async function g () { // try{ await Fun(); // }catch(e){ // console.log('错了'); // } console.log( 123 );

mem系列与str系列函数了解

匿名 (未验证) 提交于 2019-12-03 00:28:02
系列函数通常处理内存内容,而Str通常处理字符串,这俩个家族系列函数经常会使用,在网上搜集了一些资料进行了整理,方便自己以后查阅,下面介绍了memcpy,strcpy,strncpy,memmove,memcmp,strcmp,strcat,strstr,strtok等函数: 函数原型 :void *memcpy(void *dest, const void *src,size_t n); 函数功能 :内存拷贝;将src指向内存地址的连续N个指针位置的内容拷贝至dest指针指向的位置 函数返回 :无 参数说明 : dest ― 目的内存空间指针 src ― 源内存 n ― 拷贝指针位置个数 # include <memory> include <iostream> include < string > void main() { char * src = “Hello Frankie World !”; char * dest = new char [ 50 ]; memset (dest, 0 , 50 ); memcpy (dest,src, 7 ); std :: cout <<”dset值为:”<< std ::endl; Out(dest); } 函数原型 :void * memccpy(void *dest, void *src, unsigned char c,

向量vector 容器浅析

坚强是说给别人听的谎言 提交于 2019-12-03 00:17:54
一、什么是vector? 向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。 二、容器特性 1.顺序序列 顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。 2.动态数组 支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。操供了在序列末尾相对快速地添加/删除元素的操作。 3.能够感知内存分配器的(Allocator-aware) 容器使用一个内存分配器对象来动态地处理它的存储需求。 三、基本函数实现 1.构造函数 vector():创建一个空vector vector(int nSize):创建一个vector,元素个数为nSize vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t vector(const vector&):复制构造函数 vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中 2.增加函数 void push_back(const T& x):向量尾部增加一个元素X iterator insert(iterator it,const T& x)