time,gettimeofday,clock_gettime,_ftime

time()提供了秒级的精确度
1、头文件 <time.h>
2、函数原型
time_t time(time_t * timer)
函数返回从TC1970-1-1 0:0:0开始到现在的秒数
用time()函数结合其他函数(如:localtime、gmtime、asctime、ctime)可以获得当前系统时间或是标准时间。
#include <time.h>
#include <stdio.h>
int main(void)
{
    time_t t;
    t = time(NULL);
    printf("The number of seconds since January 1, 1970 is %ld",t);
    return 0;
}
#include <stdio.h>
#include <stddef.h>
#include <time.h>
int main(void)
{
    time_t timer;//time_t就是long int 类型
    struct tm *tblock;
    timer = time(NULL);//这一句也可以改成time(&timer);
    tblock = localtime(&timer);
    printf("Local time is: %s/n",asctime(tblock));
    return 0;
}

 

gettimeofday()提供了微秒级的精确度
1、头文件 <time.h>
2、函数原型
int gettimeofday(struct timeval *tv, struct timezone *tz);
gettimeofday()会把目前的时间由tv所指的结构返回,当地时区的信息则放到tz所指的结构中(可用NULL)。
参数说明:
    timeval结构定义为:
    struct timeval
    {
        long tv_sec; /*秒*/
        long tv_usec; /*微秒*/
    };
    timezone 结构定义为:
    struct timezone
    {
        int tz_minuteswest; /*和Greenwich 时间差了多少分钟*/
        int tz_dsttime; /*日光节约时间的状态*/
    };
    上述两个结构都定义在/usr/include/sys/time.h。tz_dsttime 所代表的状态如下
        DST_NONE /*不使用*/
        DST_USA /*美国*/
        DST_AUST /*澳洲*/
        DST_WET /*西欧*/
        DST_MET /*中欧*/
        DST_EET /*东欧*/
        DST_CAN /*加拿大*/
        DST_GB /*大不列颠*/
        DST_RUM /*罗马尼亚*/
        DST_TUR /*土耳其*/
        DST_AUSTALT /*澳洲(1986年以后)*/
返回值: 成功则返回0,失败返回-1,错误代码存于errno。附加说明EFAULT指针tv和tz所指的内存空间超出存取权限。
#include<stdio.h>
#include<time.h>
int main(void)
{
    struct timeval tv;
    struct timezone tz;
    gettimeofday (&tv , &tz);
    printf(“tv_sec; %d/n”, tv,.tv_sec) ;
    printf(“tv_usec; %d/n”,tv.tv_usec);
    printf(“tz_minuteswest; %d/n”, tz.tz_minuteswest);
    printf(“tz_dsttime, %d/n”,tz.tz_dsttime);
    return 0;
}

 

clock_gettime( ) 提供了纳秒级的精确度
1、头文件 <time.h>
2、编译&链接。在编译链接时需加上 -lrt ;因为在librt中实现了clock_gettime函数
3、函数原型
int clock_gettime(clockid_t clk_id, struct timespect *tp);
    参数说明:
    clockid_t clk_id 用于指定计时时钟的类型,有以下4种:
        CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户该成其他,则对应的时间相应改变
        CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
        CLOCK_PROCESS_CPUTIME_ID:本进程到当前代码系统CPU花费的时间
        CLOCK_THREAD_CPUTIME_ID:本线程到当前代码系统CPU花费的时间
    struct timespect *tp用来存储当前的时间,其结构如下:
        struct timespec
        {
            time_t tv_sec; /* seconds */
            long tv_nsec; /* nanoseconds */
        };
    返回值。0成功,-1失败
#include<stdio.h>
#include<time.h>
int main()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    printf("CLOCK_REALTIME: %d, %d", ts.tv_sec, ts.tv_nsec);
    clock_gettime(CLOCK_MONOTONIC, &ts);//打印出来的时间跟 cat /proc/uptime 第一个参数一样
    printf("CLOCK_MONOTONIC: %d, %d", ts.tv_sec, ts.tv_nsec);
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
    printf("CLOCK_PROCESS_CPUTIME_ID: %d, %d", ts.tv_sec, ts.tv_nsec);
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
    printf("CLOCK_THREAD_CPUTIME_ID: %d, %d", ts.tv_sec, ts.tv_nsec);
    printf("/n%d/n", time(NULL));
    return 0;
}
/proc/uptime里面的两个数字分别表示:
the uptime of the system (seconds), and the amount of time spent in idle process (seconds).
把第一个数读出来,那就是从系统启动至今的时间,单位是秒

 

_ftime()提供毫秒级的精确度
1、头文件 <sys/types.h> and <sys/timeb.h>
2、函数原型
void _ftime(struct _timeb *timeptr);
参数说明:
    struct _timeb
    {
        time_t time;
        unsigned short millitm;
        short timezone;
        short dstflag;
    };
#include <stdio.h>
#include <sys/timeb.h>
#include <time.h>
void main( void )
{
    struct _timeb timebuffer;
    char *timeline;
    _ftime( &timebuffer );
    timeline = ctime( & ( timebuffer.time ) );
    printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );
}

 
reference:
http://blog.csdn.net/wind19/article/details/12975173
http://blog.csdn.net/sunlylorn/article/details/6313278

C++程序运行时内存布局——this

非静态成员函数,无论是不是虚函数,都隐藏了一个this指针参数。这个参数的目的就是给函数提供一个基地址,以便于函数体内能找到对象的成员变量。那非静态成员函数是如何根据this指针找到成员变量的呢?直接看例子吧
1 没有虚表的情况

#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
	   int x;
   	int y;
public:
	void F1()
	{
   		this->x = 1;
   		this->y = 2;
   		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
int main(int argc, char** argv)
{
   	A a;
   	cout<<"a对象的地址是:"<<&a<<endl;
	   cout<<"a对象的大小是:"<<sizeof(A)<<endl;
	   cout<<"成员a.x的地址是: "<<&a.x<<endl;
   	cout<<"成员a.x的偏移是:"<<&A::x<<endl;
	   a.F1();
	   cin>>argc;
	   return 0;
}

那么函数F1的实现伪代码为:
*(this+&A::x-1) = 1;
*(this+&A::y-1) = 2;
其中&A::x是成员x的偏移+1,&A::y是成员y的偏移+1,这可是C++基本语法的知识,希望你知道,呵呵。可这些偏移量是相对应那里的偏移呢,是对象地址吗,答案是NO。是相对于第一个成员变量的偏移,这对于有些对象也许没有差别,但是对于有虚表的类的对象,就有差别了。这些偏移在编译期间就是确定了的。对于本例在VC++2010下&A::x,值为1, &A::y,值为5。为什么不是0,4,请看《Inside The C++ Object Model》。
所以,对于找到成员变量,需要进一步确定的只有this的值。程序运行结果如下:

可见此例中,对象的地址与this指针的地址相同,内存图如下所示。

2 有一个虚表的情况

#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
   	int x;
	   int y;
public:
	virtual void F1()
	{
		   this->x = 1;
		   this->y = 2;
   		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
int main(int argc, char** argv)
{
   	A* p = new A();
   	cout<<"a对象的地址是:"<<p<<endl;
	   cout<<"a对象的大小是:"<<sizeof(A)<<endl;
   	cout<<"成员a.x的地址是: "<<&p->x<<endl;
   	cout<<"成员a.x的偏移是:"<<&A::x<<endl;
	   p->F1();
   	cin>>argc;
   	return 0;
}

此时函数F1的实现伪代码为:
*(this+4+&A::x-1) = 1;  //+4是因为存在虚表指针
*(this+4+&A::y-1) = 2;  //+4是因为存在虚表指针
程序运行结果如下:

内存布局如下:

结论:this的值和对象地址相同,成员变量偏移量不因虚表指针存在而改变。带虚表的类的成员函数对成员变量的寻址方式不同,增加一个+4。
3 单继承的情况

#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
	int x;
	int y;
public:
	void F1()
	{
		this->x = 1;
		this->y = 2;
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
class B : public A
{
public:
	int z;
public:
	virtual void F2()
	{
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
int main(int argc, char** argv)
{
	B* pb = new B();
	cout<<"对象的地址为:"<<std::hex<<std::showbase<<pb<<endl;
	pb->F1();
	pb->F2();
	cin>>argc;
	return 0;
}

运行结果:

内存布局:

结论:this指针的值受两个因素确定,一是对象的地址,二是定义成员函数的类。This指向的是对象内,定义该方法的类得subobject。
4 多继承的情况
先看A没有虚函数,B有虚函数的情况

#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
	int x;
	int y;
public:
	void F1()
	{
		this->x = 1;
		this->y = 2;
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
class B
{
public:
	int z;
public:
	virtual void F2()
	{
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
class C : public A, public B
{
public:
	int a;
public:
	virtual void F2()
	{
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
	void F3()
	{
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
int main(int argc, char** argv)
{
	C* pc = new C();
	cout<<"对象的大小为:"<<sizeof(C)<<endl;
	cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl;
	pc->F1();
	pc->F2();
	pc->F3();
	cin>>argc;
	return 0;
}

结果:

内存布局:

再看,如果A,B都有虚函数的情况。
代码:

#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
	int x;
	int y;
public:
	virtual void F1()
	{
		this->x = 1;
		this->y = 2;
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
class B
{
public:
	int z;
public:
	virtual void F2()
	{
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
class C : public A, public B
{
public:
	int a;
public:
	virtual void F2()
	{
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
	void F3()
	{
		cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
	}
};
int main(int argc, char** argv)
{
	C* pc = new C();
	cout<<"对象的大小为:"<<sizeof(C)<<endl;
	cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl;
	cout<<"x的地址"<<&pc->x<<endl;
	cout<<"z的地址"<<&pc->z<<endl;
	pc->F1();
	pc->F2();
	pc->B::F2();
	pc->F3();
	cin>>argc;
	return 0;
}

结果:

内存布局:

结论:再一次验证了this指针的值的确定方法,this始终要保证指向定义了该成员函数的类得subobject。因为C++保证base class subobject与base class object完全对应,从而保证了成员函数能根据成员变量在定义了该变量的类中的偏移寻址。
转自:http://blog.csdn.net/smstong/article/details/6604388

C++四种cast——static_cast、dynamic_cast、reinterpret_cast、和const_cast

a) reinterpret_cast 转换一个指针为其他类型的指针,它也允许一个指针转换成整型。反之亦然。不做任何类型检查。
用 法:reinpreter_cast< type-id> (expression)
type-id必须是一个 指针、引用、算术类型、函数指针或者成员指针。
b) static_cast 允许执行任意的隐式转换和相反转换动作。不做类型检查。最接近C-Style的转换。
用 法:static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:

  • 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全 的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
  • 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
  • 把空指针转换成目标类型的空指针。
  • 把 任何类型的表达式转换成void类型。

注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
c) dynamic_cast 只用于对象的指针和引用,会检查操作是否有效。
用 法:dynamic_cast < type-id > ( expression )
该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void  *;如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个 引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查 的功能,比static_cast更安全。
dynamic_cast还支持交叉转换

class A{
public:
   int m_iNum;
   virtual void f(){}
};
class  B:public A{
};
class D:public A{
};
void foo(){
   B *pb = new B;
   pb->m_iNum = 100;
   D  *pd1 = static_cast<D *>(pb);    //copile error
   D *pd2 =  dynamic_cast<D *>(pb);  //pd2 is NULL
   delete pb;
}

d) const_cast 设置或移除对象的const属性。
用法:const_cast< type_id> (expression)
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。