发现许久没有来园子里逛了,一来是工作了,的确很忙,二来是手的确有点懒。想写点东西,找来找去,还是对这个园子有感情。
最近发现懒惰真的是一个很容易养成的习惯,它会慢慢吞噬掉一切。就项目而言,压力的确比学生时要繁重许多,但条理性似乎更加重要。随手记下,随时总结总归是好的,一个回头,就不知道什么是时候是个头了。
所以半年多的经验来看,一定要及时的总结项目,要把最新鲜的,最热气腾腾的东西记录下来。
对自己回顾是一个帮助,对他人入门也是个捷径。
养成及时总结的习惯很重要。
posted @
2010-11-16 23:34 Sandy 阅读(353) |
评论 (0) |
编辑 收藏
今天是一个非常开心的日子,我拿到了我梦寐以求的一家公司的offer,可以继续沿着梦想的道路继续前进,开心。
首先感谢默默支持我的人,在这一路寻找的路上,有过很多挫折,谢谢他们给我的力量,让我越挫越勇。
其次感谢一次次面试中给了我很多帮助的面试官,其实面试是一个互相学习的机会,而且每一次的肯定都是对能力的一种肯定,给了我很多信心。最后可能由于各种原因,与一些公司擦肩而过,也衷心祝愿这些公司的发展越来越好。
最后感谢给了我很多建议的人,让我一路坚持梦想的走下来。 软件开发,是我热爱的一个方向,我也希望能够沿着这条路继续走下去。
小小广告,如果你的网络很慢,不妨试试Opera的Turbo加速,不一般的体验啊!
posted @
2009-12-21 22:29 Sandy 阅读(478) |
评论 (3) |
编辑 收藏
摘自:
http://liuaigui.blog.sohu.com/86494742.html线程安全的(Thread-Safe):如果一个函数在同一时刻可以被多个线程安全地调用,就称该函数是线程安全的。线程安全函数解决多个线程调用函数时访问共享资源的冲突问题。
可重入(Reentrant):函数可以由多于一个线程并发使用,而不必担心数据错误。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入性解决函数运行结果的确定性和可重复性。可重入函数编写规范为:
1、不在函数内部使用静态或全局数据
2、不返回静态或全局数据,所有数据都由函数的调用者提供。
3、使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
4、如果必须访问全局变量,利用互斥机制来保护全局变量。
5、不调用不可重入函数。
两者之间的关系:
1、一个函数对于多个线程是可重入的,则这个函数是线程安全的。
2、一个函数是线程安全的,但并不一定是可重入的。
3、可重入性要强于线程安全性。
比如:strtok函数是既不可重入的,也不是线程安全的。加锁的strtok不是可重入的,但线程安全。而strtok_r既是可重入的,也是线程安全的
之所以会去查这个问题,是在考试中遇到过考strtok这个问题是否可用于多线程。自己从使用的角度上感觉不安全,但是究其原因却不是很明白。查了一下,居然涉及到函数的线程安全。
在另一篇博文中,是这样解释的:
strtok不是一个线程安全的函数。因为根据其定义,它必须使用内部静态变量来记录字符串中下一个需要解析的标记的当前位置。但是,由于指示这个位置的变量只有一个,那么,在同一个程序中出现多个解析不同字符串的strtok调用时,各自的字符串的解析就会互相干扰。(摘自:
http://hi.baidu.com/pigfanfan/blog/item/72816c958d63e743d1135ebf.html)
怎么避免呢?
我们可以利用另一个函数:strtok_r,这个是一个线程安全的函数——strtok_r,以此来代替strtok。
posted @
2009-10-22 17:33 Sandy 阅读(1573) |
评论 (0) |
编辑 收藏
转:C++ pair用法
摘自:
http://hi.baidu.com/lucene1983/blog/item/83bb68351d12ffbed1a2d3fe.html1 pair的应用
pair是将2个数据组合成一个数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。 pair的实现是一个结构体,主要的两个成员变量是first second 因为是使用struct不是class,所以可以直接使用pair的成员变量。
2 make_pair函数
template pair make_pair(T1 a, T2 b) { return pair(a, b); }
很明显,我们可以使用pair的构造函数也可以使用make_pair来生成我们需要的pair。 一般make_pair都使用在需要pair做参数的位置,可以直接调用make_pair生成pair对象很方便,代码也很清晰。 另一个使用的方面就是pair可以接受隐式的类型转换,这样可以获得更高的灵活度。灵活度也带来了一些问题如:
std::pair<int, float>(1, 1.1);
std::make_pair(1, 1.1);
是不同的,第一个就是float,而第2个会自己匹配成double。
以上是从网上找来的资料,我又查了一下关于pair的定义,其定义是一个模板结构。
// TEMPLATE STRUCT pair
template<class _Ty1,
class _Ty2> struct pair
{ // store a pair of values
typedef pair<_Ty1, _Ty2> _Myt;
typedef _Ty1 first_type;
typedef _Ty2 second_type;
pair()
: first(_Ty1()), second(_Ty2())
{ // construct from defaults
}
pair(const _Ty1& _Val1, const _Ty2& _Val2)
: first(_Val1), second(_Val2)
{ // construct from specified values
}
template<class _Other1,
class _Other2>
pair(const pair<_Other1, _Other2>& _Right)
: first(_Right.first), second(_Right.second)
{ // construct from compatible pair
}
void swap(_Myt& _Right)
{ // exchange contents with _Right
std::swap(first, _Right.first);
std::swap(second, _Right.second);
}
_Ty1 first; // the first stored value
_Ty2 second; // the second stored value
};
make_pair同样也是一个模板函数。其定义如下:
template<class _Ty1,
class _Ty2> inline
pair<_Ty1, _Ty2> make_pair(_Ty1 _Val1, _Ty2 _Val2)
{ // return pair composed from arguments
return (pair<_Ty1, _Ty2>(_Val1, _Val2));
}
posted @
2009-10-15 11:09 Sandy 阅读(12012) |
评论 (0) |
编辑 收藏
有这么一个关于虚函数和虚继承的问题,如下:
class A
{
char k[3];
public:
virtual void aa();
};
class B: public virtual A
{
char j[3];
public:
virtual void bb();
};
class C: public virtual B
{
char i[3];
public:
virtual void cc();
};
请问sizeof(A), sizeof(B), sizeof(C)分别为多少?
对于A, 我们很清楚的知道,其大小为8。
对于B,考虑到虚继承和自身的虚函数,我们也可以算出来起大小为8+8+4 = 20
对于C,其大小为20+8+4 = 32。
其中 4为虚继承所占用的指针。
这个看上去没有什么问题。但是当我把虚继承去掉以后,这里却有了一些变化?
首先,我猜想了一下,A是8,B是16,C是24。
可惜结果和我想的不一样,答案是8, 12, 16。很有规律的一个数字。
从A到B,只增加了4。什么原因呢?
在http://www.diybl.com/course/3_program/c++/cppjs/2007927/74925.html这里介绍了一些
The existence of virtual function(s)
Existence of virtual function(s) will add 4 bytes of virtual table pointer in the class, which will be added to size of class. Again, in this case, if the base class of the class already has virtual function(s) either directly or through its base class, then this additional virtual function won't add anything to the size of the class. Virtual table pointer will be common across the class hierarchy. That is
class Base {
public:
...
virtual void SomeFunction(...);
private:
int iAMem
};
class Derived : public Base
{
...
virtual void SomeOtherFunction(...);
private:
int iBMem
};
In the example above, sizeof(Base) will be 8 bytes--that is sizeof(int iAMem) + sizeof(vptr). sizeof(Derived) will be 12 bytes, that is sizeof(int iBMem) + sizeof(Derived). Notice that the existence of virtual functions in class Derived won't add anything more. Now Derived will set the vptr to its own virtual function table.
派生类和基类拥有相同的虚函数表。
但似乎虚继承的时候,又摈弃了这一做法。
所以两个是有所区别的。
posted @
2009-10-07 22:43 Sandy 阅读(1935) |
评论 (2) |
编辑 收藏
今天在看面试宝典,注意到上面所说浮点数在内存里和整数的存储方式不同,但究竟有何不同呢?
在网上搜了一下:
在http://blog.csdn.net/djsl6071/archive/2007/03/16/1531336.aspx中介绍了浮点数在内存中的存储方式,觉得不错,转过来。
浮点数在内存中的存储方式
浮点数保存的字节格式如下:
地址 +0 +1 +2 +3
内容 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
这里
S 代表符号位,1是负,0是正
E 偏移127的幂,二进制阶码=(EEEEEEEE)-127。
M 24位的尾数保存在23位中,只存储23位,最高位固定为1。此方法用最较少的位数实现了
较高的有效位数,提高了精度。
零是一个特定值,幂是0 尾数也是0。
浮点数-12.5作为一个十六进制数0xC1480000保存在存储区中,这个值如下:
地址 +0 +1 +2 +3
内容0xC1 0x48 0x00 0x00
浮点数和十六进制等效保存值之间的转换相当简单。下面的例子说明上面的值-12.5如何转
换。
浮点保存值不是一个直接的格式,要转换为一个浮点数,位必须按上面的浮点数保存格式表
所列的那样分开,例如:
地址 +0 +1 +2 +3
格式 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
二进制 11000001 01001000 00000000 00000000
十六进制 C1 48 00 00
从这个例子可以得到下面的信息:
符号位是1 表示一个负数
幂是二进制10000010或十进制130,130减去127是3,就是实际的幂。
尾数是后面的二进制数10010000000000000000000
在尾数的左边有一个省略的小数点和1,这个1在浮点数的保存中经常省略,加上一个1和小数
点到尾数的开头,得到尾数值如下:
1.10010000000000000000000
接着,根据指数调整尾数.一个负的指数向左移动小数点.一个正的指数向右移动小数点.因为
指数是3,尾数调整如下:
1100.10000000000000000000
结果是一个二进制浮点数,小数点左边的二进制数代表所处位置的2的幂,例如:1100表示
(1*2^3)+(1*2^2)+(0*2^1)+(0*2^0)=12。
小数点的右边也代表所处位置的2的幂,只是幂是负的。例如:.100...表示(1*2^(-1))+
(0*2^(-2))+(0*2^(-2))...=0.5。
这些值的和是12.5。因为设置的符号位表示这数是负的,因此十六进制值0xC1480000表示-
12.5。
关于多字节数据类型在内存中的存储问题
int ,short 分别是4、2字节。他们在内存中的存储方式下面举个例子说明。
int data = 0xf4f3f2f1;
其中低位存放在编址小的内存单元,高位存放在编址高的内存单元
如下:
地址:0x8000 0x8001 0x8002 0x8003
数据: f1 f2 f3 f4
根据IEEE在1985年制定的标准来处理浮点数
单精度浮点数用4字节,包括1位符号位s(整数为0,负数为1),8位指数位e,23位有效位f
浮点型使用的是科学计数法,比如十进制的12345可以表示为1.2345 * 10^4(表示10的4次幂)
用二进制表示为 1.1000000111001 * 2^13
所以计算机中用浮点数表示12345这个十进制应该是这样的,s位为0,因为是正数,指数位为13+127=140(127为单精度浮点数偏移值,为了表示只有小数部分的数),有效位为1000000111001
计算的时候用 (-1)^s * 1.f * 2^(e-127) ,结果就是 1* 1.1000000111001 * 2^(140-127=13) ,和我们刚才表示的一样
还比如,十进制小数0.125转换为二进制小数0.001可以表示为 1* 1.0 * 2^(124-127=-3)
double,双精度浮点数有1位符号位、11位指数位和52位有效数
谢谢,和我找的资料差不多:)
知道公式
n=(-1)^s*m*2^e
e=|E|-bias
bias = 2^(k-1)-1(k为E的位数)
m=|1.M|
知道12345在内存中的10进制表示以后
0x4640e400 = 0(100 0110 0)<100 0000 1110 0100 0000>
括号中的数字为|E| = 140 所以e=140-127=13
尖括号中的数字为m=|1.M|=|1.100000011100100|=1.506958008
ok,
代入公式n = (-1)^0*1.506958008*2^13=12345
完工!!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/edivista/archive/2009/06/07/4248794.aspx
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/edivista/archive/2009/06/07/4248794.aspx
posted @
2009-10-02 20:51 Sandy 阅读(1036) |
评论 (0) |
编辑 收藏
DLL, 动态链接库, Dynamic-link library.一直以来都是Windows操作系统的基石。Window应用程序编程接口提供的所有函数都包含在DLL中。其中三个最重要的DLL分别是Kernel32.dll,User32.dll,GDI32.dll。Kernel32.dll ,包含的函数用来管理内存、进程以及线程;User32.dll包含的函数用来执行与用户界面相关的任务,如创建窗口和发送消息。GDI32.dll,包含的函数用来绘制图像和显示文字。Windows Mobile中重要的DLL是Coredll.dll.
Windows系统广泛使用DLL,那么我们使用DLL的理由是什么?下面是在《Windows 核心编程中》摘录的一部分:
一是扩展了应用程序的特性;
二是简化了项目的管理;
三是有助于节省内存;
四是促进了资源的共享;
五是促进了本地化;
六是有助于解决平台间的差异;
七是可以用于特殊目的。
目前用到的地方在 节省内存、资源共享、本地化、特殊目的。这几个是我在项目中见过的。DLL如何使用呢?一般有两种方法,一是隐式载入时链接(implicit load-time linking)和显示运行时链接(explicit run-time linking)。
隐式链接,常用的方法是将DLL的头文件和LIB文件包含到执行文件程序中,相应DLL放到执行文件对应的目录。基本就OK了。
例如:
DLL为MyLib.dll,其头文件为MyLib.h, LIB文件为MyLib.lib。
我们在执行文件中使用是,需要做如下操作:
#include "MyLib.h"
#pragma comment(lib, "MyLib.lib")
即可实现隐式调用,变量、函数、类就可实现调用。
这里lib文件非常小,它并不包含任何函数或变量,它只是列出了所有被导出的函数和变量的变量名,具体的实现在dll文件中。编译阶段不包含Lib文件会出错的。
显示链接,在应用程序运行的过程中,显示地载入所需的DLL。
一般可以使用LoadLibrary和FreeLibrary来实现加载和卸载DLL。那么如何判断一个DLL是否已经被映射到了进程的地址空间中?我们可以使用GetModuleHandle.
如:
HMODULE hInstDll = GetModuleHandle(TEXT("MyLib"));
if (hInstDll == NULL)
{
hInstDll = LoadLibrary(TEXT("MyLib"));
}
我们已经知道如何显示加载DLL,那如何显示调用其中的变量、函数、类呢?
例如在DLL中,我们有一个变量 g_nResult, 函数Add,我们在执行程序中如何调用呢?可以利用GetProcAddress。
对于变量:
int nResult =*(int*)GetProcAddress(hInstDll, "g_nResult");
对于函数:
typedef int (*FUNC)(int, int);
FUNC pfn = (FUNC)GetProcAddress(hInstDll, "Add");
这是今天学习到的关于DLL的一点知识。
posted @
2009-10-02 16:43 Sandy 阅读(669) |
评论 (0) |
编辑 收藏