内存释放了为什么还能使用
int* p=new int[10]; //你向房东租了间房子,房东给你一把钥匙p
p[0]=1234; //你开始使用这间房子,扔了一堆你的东西
delete[] p; //你向房东退房了
//p=NULL; //你把钥匙还了,如果没有这句就是你没还钥匙
cout <<p[0]; //你明明退了房子,但没有还钥匙。然后还用这把钥匙开门进去。
//这时有三种结果:(1)房子还是老样子,你扔的东西都还在,就像你没退房一样
// (2) 房子已经被房东收拾过了,你的东西被扔掉了。
// (3) 房子已经被租给其他人了,你被当做小偷暴打了一顿。
最后,请记住:退房记得还钥匙。
获取系统版本号:
OSVERSIONINFO osi;
ZeroMemory(&osi,sizeof(OSVERSIONINFO));
osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osi);
//判断系统是否是XP
if (osi.dwMinorVersion >= 1 && osi.dwMajorVersion == 5)
{
}
else
{
}
_T()
VC++里面定义字符串的时候,用_T来保证兼容性。VC++支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。
_t("hello world")
在ansi的环境下,它是ansi的,如果在unicode下,那么它将自动解释为双字节字符串,既unicode编码。
这样做的好处,不管是ansi环境,还是unicode环境,都适用。
那么在VC++中,字符串_T("ABC")和一个普通的字符串"ABC"有什么区别呢?
_T("ABC")
如果定义了unicode,它将表示为L"ABC",每个字符为16位,宽字符串。
如果没有定义unicode,它就是ascii的"ABC",每个字符为8位。
相当于
#ifdef _UNICODE
#define _T("ABC") L"ABC"
#else
#define _T("ABC") "ABC"
#endif
_T("ABC")中的一个字符和汉字一样,占两个字节,而在"ABC"中,英文字符占一个字节,汉字占两个字节。
在字符串前加一个L作用:
如 L"我的字符串" 表示将ANSI字符串转换成unicode的字符串,就是每个字符占用两个字节。
strlen("asd") = 3;
strlen(L"asd") = 6;
static 类成员
非 static 数据成员存在于类类型的每个对象中。不像普通的数据成员,static 数据成员独立于该类的任意对象而存在;
每个 static 数据成员是与类关联的对象,并不与该类的对象相关联。
正如类可以定义共享的 static 数据成员一样,类也可以定义 static 成员函数。static 成员函数没有 this 形参,它可以直接访问所属类的 static 成
员,但不能直接使用非 static 成员。
static成员函数的定义:
class Account {
public:
// interface functions here
void applyint() { amount += amount * interestRate; }
static double rate() { return interestRate; }
static void rate(double); // sets a new rate
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
};
Account 类有两个名为 rate 的 static 成员函数,其中一个定义在类的内
部。当我们在类的外部定义 static 成员时,无须重复指定 static 保留字,该
保留字只出现在类定义体内部的声明处:
void Account::rate(double newRate)
{
interestRate = newRate;
}
因为 static 成员不是任何对象的组成部分,所以 static 成员函数不能被
声明为 const。毕竟,将成员函数声明为 const 就是承诺不会修改该函数所属
的对象。 最后, static 成员函数也不能被声明为虚函数。
二进制字符串转换为浮点型字符串
float f=0.0;
unsigned char i,*p,fc[]={0x65,0x88,0x76,0x40},fd[33]={0};//float占4个字节
p=(unsigned char *)&f;
for (i=0;i<4;i++)
p[i]=fc[i];
for (i=0;i<4;i++)
printf("%x\t",p[i]);
printf("%f\n",f);
sprintf((char *)fd,"%.2f",f);//保留到小数点后两位
INT类型最大最小值获取
计算机中采用二进制补码存储数据。正数源码、反码、补码不变,负数需要把除符号位以后的部分取反加1
int类型:
二进制原码最大为0111111111111111=215-1=32767
二进制原码最小为1111111111111111=-(215-1)=-32767
正0和负0:0000000000000000=1000000000000000=0,补码表示中,前者的补码还是0000000000000000,后者经过非符号位取反加1后,同样变成了0000000000000000,也就是正0和负0在补码系统中的编码是一样的。
-1的16位二进制原码:1000000000000001,-1的16位二进制补码:1111111111111111。
因为任何一个原码都不可能在转成补码时变成1000000000000000。所以,人为规定1000000000000000这个补码编码为-32768。
已知补码求源码,只需将补码再求补码就得到源码:
已知补码:1111 1111 1100 0101
首先最高位为1所以为负数
反码为:1000 0000 0011 1010
原码为:1000 0000 0011 1011=-59
unsigned intGetUnsignedIntMax()
{
return ~ 0 ;
}
signed int GetSignedIntMax()
{
return ((unsigned int)( ~ 0 )) >> 1) ;//(unsigned int)( ~ 0 ) 为:1111....1111 ; >>1之后为:0111....1111
}
int int_min = ~(unsigned int(-1) >> 1);
http://blog.csdn.net/gzydulala/article/details/22332087
头文件 <limits.h> 、<float.h>
inet_addr实现原理
转:http://blog.csdn.net/brk1985/article/details/17032433
输入是点分的IP地址格式(如A.B.C.D)的字符串,从该字符串中提取出每一部分,转换为ULONG,假设得到4个ULONG型的A,B,C,D,
ulAddress(ULONG型)是转换后的结果,
ulAddress = D<<24 + C<<16 + B<<8 + A(网络字节序),即inet_addr(const char *)的返回结果
另外我们也可以得到把该IP转换为主机序的结果,转换方法一样
A<<24 + B<<16 + C<<8 + D
NEW异常捕获
vc6.0不支持new异常抛出,new分配失败直接返回NULL;
构造函数中new异常捕获:
转:http://blog.csdn.net/hywbd/article/details/5338818
win32下C++线程同步机制
线程的同步可分用户模式的线程同步和内核对象的线程同步两大类。用户模式中线程的同步方法主要有原子访问和临界区等方法。其特点是同步速度特别快,适合于对线程运行速度有严格要求的场合。
内核对象的线程同步则主要由事件、等待定时器、信号量以及信号灯等内核对象构成。由于这种同步机制使用了内核对象,使用时必须将线程从用户模式切换到内核模式,而这种转换一般要耗费近千个CPU周期,因此同步速度较慢,但在适用性上却要远优于用户模式的线程同步方式。
在WIN32中,同步机制主要有以下几种:
(1)事件(Event);
(2)信号量(semaphore);
(3)互斥量(mutex);
(4)临界区(Critical section)。
临界区:
CRITICAL_SECTION cs;
InitializeCriticalSection( & cs);
// 线程1:
EnterCriticalSection( & cs);
int a = s.a;
int b = s.b;
LeaveCriticalSection( & cs);
// 线程2
EnterCriticalSection( & cs);
s.a ++ ;
s.b -- ;
LeaveCriticalSection( & cs);
// 最后:
DeleteCriticalSection( & cs);
详细介绍 转:http://blog.csdn.net/theplayerwuliang/article/details/6431722
事件
事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。根据状态变迁方式的不同,事件可分为两类:
(1)手动设置:这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。
(2)自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。
使用"事件"机制应注意以下事项:
(1)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
(2)事件是否要自动恢复;
(3)事件的初始状态设置。
由于event对象属于内核对象,故进程B可以调用OpenEvent函数通过对象的名字获得进程A中event对象的句柄,然后将这个句柄用于ResetEvent、SetEvent和WaitForMultipleObjects等函数中。此法可以实现一个进程的线程控制另一进程中线程的运行,例如:
HANDLE hEvent=OpenEvent(EVENT_ALL_ACCESS,true,"MyEvent");
ResetEvent(hEvent);
信号量
信号量是维护0到指定最大值之间的同步对象。信号量状态在其计数大于0时是有信号的,而其计数是0时是无信号的。信号量对象在控制上可以支持有限数量共享资源的访问。
信号量的特点和用途可用下列几句话定义:
(1)如果当前资源的数量大于0,则信号量有效;
(2)如果当前资源数量是0,则信号量无效;
(3)系统决不允许当前资源的数量为负值;
(4)当前资源数量决不能大于最大资源数量。
创建信号量
HANDLE CreateSemaphore (
PSECURITY_ATTRIBUTE psa,
LONG lInitialCount, //开始时可供使用的资源数
LONG lMaximumCount, //最大资源数
PCTSTR pszName);
释放信号量
通过调用ReleaseSemaphore函数,线程就能够对信标的当前资源数量进行递增,该函数原型为:
BOOL WINAPI ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount, //信号量的当前资源数增加lReleaseCount
LPLONG lpPreviousCount
);
打开信号量
和其他核心对象一样,信号量也可以通过名字跨进程访问,打开信号量的API为:
HANDLE OpenSemaphore (
DWORD fdwAccess,
BOOL bInherithandle,
PCTSTR pszName
);
互锁访问
当必须以原子操作方式来修改单个值时,互锁访问函数是相当有用的。所谓原子访问,是指线程在访问资源时能够确保所有其他线程都不在同一时间内访问相同的资源。
LONG
__cdecl InterlockedExchangeAdd(
_Inout_
LONG
volatile
* Addend,
_In_
LONG
Value
);
|
常用函数
memcmp()函数
从一个字符串中读进与指定格式相符的数据。
nt sscanf(const char *buffer,const char *format,[argument ]...);
sscanf会从buffer里读进数据,依照format的格式将数据写入到argument里。
成功则返回参数数目,失败则返回-1,
strtok()函数
sprintf()函数
字串格式化命令,主要功能是把格式化的数据写入某个字符串中。
int sprintf( char *buffer, const char *format, [ argument] … );
buffer:char型指针,指向将要写入的字符串的缓冲区。 format:格式化字符串。 [argument]...:可选参数,可以是任何类型的数据。
返回值:字符串长度(strlen)
strstr()函数
内存管理:
转:http://blog.csdn.net/HITXuQin/article/details/12573535
C++结构体成员初始化:
C++结构体类似于类,拥有构造函数,所以结构体成员赋初值直接在构造函数中进行;
typedef struct SMySelf
{
int iLength;
BYTE byCount;
DWORD dwWide;
WORD wLength;//word(unsigned short)
bool bIsTrue;
long lHeight;
short nLength;
long *lpLong;
unsigned int uLength;
unsigned long ulLength;
char cStr;
SMySelf()
{
byCount = 0;
dwWide= 0;
wLength = 0;
bIsTrue= false;
lHeight = 0;
nLength = 0;
lpLong = null;
uLength = 0;
ulLength = 0;
}
}SSMY_SELY;
标签:
VC6.0编译时警告:LINK : warning LNK4089: all references to "ole32.dll" discarded by /OPT:REF
解决方法:project->setting->link 选项卡 ,在Object/library modules框中添加ws2_32.lib