[
2007/10/10 07:30 | by turbozv ]
![不指定 不指定](images/weather/blank.gif)
还是一个栈变量的问题,请问以下赋值有什么不同?
{0}的方式是我们常用的初始化数组,结构的方法。
我第一次见到这个是从别人的代码里,于是之后我也没有多想就直接使用了,后来看了汇编,我才发现,原来{0}和{}是不同的。
编译器生成的代码也不同。
Release模式,关闭优化
Release模式,完全优化
结论:
看到了吧,其实{}比{0}生成的代码更优化,所以下次记得要写{}了,不要加0~![grin](images/emot/grin.gif)
其实不要说其他公司,M$里也很多{0}的代码,呵呵~~
补充:
发现Microsoft Embeded Visual C++ 3.0不支持 {},只能用{0}.....
引用
#define LEN 0xff
unsigned char a[LEN] = {0};
unsigned char b[LEN] = {};
unsigned char c[LEN] = {1};
unsigned char a[LEN] = {0};
unsigned char b[LEN] = {};
unsigned char c[LEN] = {1};
{0}的方式是我们常用的初始化数组,结构的方法。
我第一次见到这个是从别人的代码里,于是之后我也没有多想就直接使用了,后来看了汇编,我才发现,原来{0}和{}是不同的。
编译器生成的代码也不同。
Release模式,关闭优化
引用
unsigned char a[LEN] = {0};
004017E9 mov byte ptr [a],0 -- 第一个元素单独赋值0
004017F0 push 0FEh -- 所以只剩下0xff - 1 = 0xfe个元素需要调用memset了
004017F5 push 0
004017F7 lea eax,[ebp-0FFh]
004017FD push eax
004017FE call memset (401840h)
00401803 add esp,0Ch
unsigned char b[LEN] = {};
00401806 push 0FFh
0040180B push 0
0040180D lea ecx,[ b]
00401813 push ecx
00401814 call memset (401840h)
00401819 add esp,0Ch
unsigned char c[LEN] = {1};
0040181C mov byte ptr [c],1
00401823 push 0FEh
00401828 push 0
0040182A lea edx,[ebp-2FFh]
00401830 push edx
00401831 call memset (401840h)
00401836 add esp,0Ch
004017E9 mov byte ptr [a],0 -- 第一个元素单独赋值0
004017F0 push 0FEh -- 所以只剩下0xff - 1 = 0xfe个元素需要调用memset了
004017F5 push 0
004017F7 lea eax,[ebp-0FFh]
004017FD push eax
004017FE call memset (401840h)
00401803 add esp,0Ch
unsigned char b[LEN] = {};
00401806 push 0FFh
0040180B push 0
0040180D lea ecx,[ b]
00401813 push ecx
00401814 call memset (401840h)
00401819 add esp,0Ch
unsigned char c[LEN] = {1};
0040181C mov byte ptr [c],1
00401823 push 0FEh
00401828 push 0
0040182A lea edx,[ebp-2FFh]
00401830 push edx
00401831 call memset (401840h)
00401836 add esp,0Ch
Release模式,完全优化
引用
unsigned char a[LEN] = {0};
004017E6 push 0FEh -- 去掉第一个元素,只剩下0xff - 1 = 0xfe个元素需要调用memset了
004017EB lea eax,[esp+5]
004017EF push 0
004017F1 push eax
004017F2 mov byte ptr [esp+0Ch],0 -- 第一个元素单独赋值0
004017F7 call memset (401876h)
unsigned char b[LEN] = {};
004017FC push 0FFh
00401801 lea ecx,[esp+210h]
00401808 push 0
0040180A push ecx
0040180B call memset (401876h)
unsigned char c[LEN] = {1};
00401810 push 0FEh
00401815 lea edx,[esp+11Dh]
0040181C push 0
0040181E push edx
0040181F mov byte ptr [esp+124h],1
00401827 call memset (401876h)
004017E6 push 0FEh -- 去掉第一个元素,只剩下0xff - 1 = 0xfe个元素需要调用memset了
004017EB lea eax,[esp+5]
004017EF push 0
004017F1 push eax
004017F2 mov byte ptr [esp+0Ch],0 -- 第一个元素单独赋值0
004017F7 call memset (401876h)
unsigned char b[LEN] = {};
004017FC push 0FFh
00401801 lea ecx,[esp+210h]
00401808 push 0
0040180A push ecx
0040180B call memset (401876h)
unsigned char c[LEN] = {1};
00401810 push 0FEh
00401815 lea edx,[esp+11Dh]
0040181C push 0
0040181E push edx
0040181F mov byte ptr [esp+124h],1
00401827 call memset (401876h)
结论:
看到了吧,其实{}比{0}生成的代码更优化,所以下次记得要写{}了,不要加0~
![grin](images/emot/grin.gif)
其实不要说其他公司,M$里也很多{0}的代码,呵呵~~
补充:
发现Microsoft Embeded Visual C++ 3.0不支持 {},只能用{0}.....
[
2007/10/10 06:55 | by turbozv ]
![晴 晴](images/weather/sunny.gif)
阅读以下程序,写出输出结果:
很奇怪是吧,我也从来没有这样这样使用过栈对象。
我们知道,使用栈对象的好处就是编译器会在该对象生存期结束的时候自动帮我们调用它的析构函数,这就是Smart Pointer(智能指针)的理论依据。
在这个题目中,用指针p和引用a分别指向了两个栈上的临时对象A(1)和A(2),编译器将会怎样去处理它们呢?
对于临时对象A(1),它的地址被赋值给了p,然后就再也没有用了,编译器无法跟踪这个对象,于是只能在赋值以后立刻调用~A()(不然的话就没有办法释放了)
对于临时对象A(2),它被a引用,a是一个栈变量,所以可以被记录,因此~A()的调用就会在return之后。
大家看看汇编的结果吧(VS2005, 关闭Optimization,关闭Buffer Security Check)
你明白了么?来做到题目试试吧![cool](images/emot/cool.gif)
引用
class A {
private:
int _x;
public:
A(int x) {
_x = x;
printf("A(%d)\n", _x);
}
~A() {
printf("~A(%d)\n", _x);
}
};
void main()
{
A *p = &A(1);
A &a = A(2);
return;
}
private:
int _x;
public:
A(int x) {
_x = x;
printf("A(%d)\n", _x);
}
~A() {
printf("~A(%d)\n", _x);
}
};
void main()
{
A *p = &A(1);
A &a = A(2);
return;
}
很奇怪是吧,我也从来没有这样这样使用过栈对象。
我们知道,使用栈对象的好处就是编译器会在该对象生存期结束的时候自动帮我们调用它的析构函数,这就是Smart Pointer(智能指针)的理论依据。
在这个题目中,用指针p和引用a分别指向了两个栈上的临时对象A(1)和A(2),编译器将会怎样去处理它们呢?
对于临时对象A(1),它的地址被赋值给了p,然后就再也没有用了,编译器无法跟踪这个对象,于是只能在赋值以后立刻调用~A()(不然的话就没有办法释放了)
对于临时对象A(2),它被a引用,a是一个栈变量,所以可以被记录,因此~A()的调用就会在return之后。
大家看看汇编的结果吧(VS2005, 关闭Optimization,关闭Buffer Security Check)
引用
void main()
{
00401830 push ebp
00401831 mov ebp,esp
00401833 sub esp,10h
A *p = &A(1);
00401836 push 1
00401838 lea ecx,[ebp-10h]
0040183B call A::A (401000h)
00401840 mov dword ptr [p],eax
00401843 lea ecx,[ebp-10h]
00401846 call A::~A (401030h)
A &a = A(2);
0040184B push 2
0040184D lea ecx,[ebp-0Ch]
00401850 call A::A (401000h)
00401855 lea eax,[ebp-0Ch]
00401858 mov dword ptr [a],eax
return;
0040185B lea ecx,[ebp-0Ch]
0040185E call A::~A (401030h)
}
{
00401830 push ebp
00401831 mov ebp,esp
00401833 sub esp,10h
A *p = &A(1);
00401836 push 1
00401838 lea ecx,[ebp-10h]
0040183B call A::A (401000h)
00401840 mov dword ptr [p],eax
00401843 lea ecx,[ebp-10h]
00401846 call A::~A (401030h)
A &a = A(2);
0040184B push 2
0040184D lea ecx,[ebp-0Ch]
00401850 call A::A (401000h)
00401855 lea eax,[ebp-0Ch]
00401858 mov dword ptr [a],eax
return;
0040185B lea ecx,[ebp-0Ch]
0040185E call A::~A (401030h)
}
你明白了么?来做到题目试试吧
![cool](images/emot/cool.gif)
引用
请输出程序运行结果:
class A {
private:
int _x;
public:
A(int x) {
_x = x;
printf("A(%d)\n", _x);
}
~A() {
printf("~A(%d)\n", _x);
}
void set(int x) {
_x = x;
}
int get() {
return _x;
}
};
void main()
{
A &a = A(1);
A *p = &A(2);
p->set(3);
a.set(4);
printf("%d\n%d\n", p->get(), a.get());
return;
}
class A {
private:
int _x;
public:
A(int x) {
_x = x;
printf("A(%d)\n", _x);
}
~A() {
printf("~A(%d)\n", _x);
}
void set(int x) {
_x = x;
}
int get() {
return _x;
}
};
void main()
{
A &a = A(1);
A *p = &A(2);
p->set(3);
a.set(4);
printf("%d\n%d\n", p->get(), a.get());
return;
}
[
2007/02/05 02:33 | by turbozv ]
![晴 晴](images/weather/sunny.gif)
基于LibUnGif。我的目标是剥离出一套最小的,支持背景透明的,能在WinCE(PocketPC/SmartPhone)上运行的动画GIF库。
做的工作主要是几方面:
1) 增加了透明支持
2) 去掉了WinCE上不必要的一切函数
3) 写了一个Sample Code
使用方法
1)初始化Gif动画
GifWin gif;
gif.Open(gifContentBuffer, gifContentLen, RGB(0xff, 0xff, 0xff));
delay = gif.NextImage();
SetTimer(hWnd, GIF_TIMER_ID, delay, NULL);
2)显示Gif动画
WM_TIMER:
gif.Draw(hdc, left, top, right, bottom);
InvalidateRect(hdc, &rect, FALSE);
delay = gif.NextImage();
if (delay <= 0) {
gif.Reset();
delay = gif.NextImage();
}
SetTimer(hWnd, GIF_TIMER_ID, delay, NULL);
3)释放Gif动画
gif.Close();
严格遵循GPL,完整源代码下载:
下载文件
做的工作主要是几方面:
1) 增加了透明支持
2) 去掉了WinCE上不必要的一切函数
3) 写了一个Sample Code
使用方法
1)初始化Gif动画
GifWin gif;
gif.Open(gifContentBuffer, gifContentLen, RGB(0xff, 0xff, 0xff));
delay = gif.NextImage();
SetTimer(hWnd, GIF_TIMER_ID, delay, NULL);
2)显示Gif动画
WM_TIMER:
gif.Draw(hdc, left, top, right, bottom);
InvalidateRect(hdc, &rect, FALSE);
delay = gif.NextImage();
if (delay <= 0) {
gif.Reset();
delay = gif.NextImage();
}
SetTimer(hWnd, GIF_TIMER_ID, delay, NULL);
3)释放Gif动画
gif.Close();
严格遵循GPL,完整源代码下载:
![](template/woo-sapphire/images/download.gif)
[
2006/12/19 08:24 | by turbozv ]
![晴 晴](images/weather/sunny.gif)
1、Java SDK
http://java.sun.com/j2se/
2、 Sun Java(TM) Wireless Toolkit 2.5 Beta 2
http://java.sun.com/products/sjwtoolkit/download-2_5.html
3、Eclipse SDK 3.2.1
http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.2.1-200609210945/eclipse-SDK-3.2.1-win32.zip
4、EclipseME
http://nchc.dl.sourceforge.net/sourceforge/eclipseme/eclipseme.feature_1.6.0_site.zip
JBuilder被Eclipse打败确实是没有办法的事情……
http://java.sun.com/j2se/
2、 Sun Java(TM) Wireless Toolkit 2.5 Beta 2
http://java.sun.com/products/sjwtoolkit/download-2_5.html
3、Eclipse SDK 3.2.1
http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.2.1-200609210945/eclipse-SDK-3.2.1-win32.zip
4、EclipseME
http://nchc.dl.sourceforge.net/sourceforge/eclipseme/eclipseme.feature_1.6.0_site.zip
JBuilder被Eclipse打败确实是没有办法的事情……