2005年1月17日
#
今天晚上,回来一样和往常开机,当出现登陆对话框的时候,出现了声卡启动错误。
不行,本来打算晚上看堞的,出现了这个错误就没有声音了,“没有声音再好的戏也出不来呀”
点击关机按钮,反应好慢,得,reset吧。。。。。。。。。。。
重启停在那个该死的>>>
再重启,F8进安全模式,提示:system32\config\system文件已经损坏,请用安装盘修复。
ms的东西就是好,呵呵,坏了文件也这样提示,如果文件不坏就更好了,^_^。
怎么办?。。。。
借盘去(穷学生,连张安装盘都没有,我就不怕小盖来查盗版盘)
用安装盘“紧急修复”,竟然提示: 无法修复。。。。。。。。。
该死的window,老是这样耍人。
到baidu上找找吧。
咦。。。。。网络资源真是好,就像那大宝。
================================================
http://www.chinamcse.com/blog/showlog.asp?cat_id=32&log_id=384里面
win2k出现\winnt\system32\config\system丢失无法启动的现象,别着急,可以用系统启动盘修复,或者进入到recovery console里面
cd system32\config
ren system system.old
ren system.alt systemalt.old
copy c:\winnt\repair\system
运行后,应该可以启动进入win2k了。。。。。。
=================================================
按本做事,果真成功启动。。。。。。
呵呵,不过启动后,还是免不了安装显卡驱动,安装输入法,比起重装系统要简单的多了,主要是那些应用软件呀,重装一次就得一上午。
留着这个小日记,下次再有这样的问题,就到这里找。。。。。。
2004年12月26日
#
C++中的 static 关键字
前言:
本文只是本人对C++中关于静态类型的一个总结,如错误之处,请大家帮我改正。我分两个方面来总结,第一方面主要是相对于面向过程而言,即在这方面不涉及到类,第二方面相对于面向对象而言,主要说明static在类中的作用。
一、在面向过程设计中的static关键字
1、静态全局变量
定义:在全局变量前,加上关键字 static 该变量就被定义成为了一个静态全局变量。
特点:
A、该变量在全局数据区分配内存。
B、初始化:如果不显式初始化,那么将被隐式初始化为0。
C、访变量只在本源文件可见,严格的讲应该为定义之处开始到本文件结束。
例(摘于C++程序设计教程---钱能主编P103):
//file1.cpp
#include
void fn();
extern int n;
void main()
{
n=20;
cout << n << endl;
fn();
}
//file2.cpp
#include
static int n; //定义静态全局变量,初始化为0;
void fn()
{
n++;
cout << n << endl;
}
文件分别编译能通过,但连接时file1.cpp 中的变量n找不到定义,产生连接错误。
D、文件作用域下声明的const的常量默认为static存储类型。
2、静态局部变量
定义:在局部变量前加上static关键字时,就定义了静态局部变量。
特点:
A、该变量在全局数据区分配内存。
B、初始化:如果不显式初始化,那么将被隐式初始化为0。
C、它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或 语句块结束时,其作用域随之结束。
3、静态函数(注意与类的静态成员函数区别)
定义:在函数的返回类型前加上static关键字,函数即被定义成静态函数。
特点:
A、静态函数只能在本源文件中使用(这是与普通函数区别)
例(摘于C++程序设计教程---钱能主编P103):
//file1.cpp
void fn();
void staticFn()
void main()
{
fn();
staticFn();
}
//file2.cpp
#include
static void staticFn();
void fn();
void fn()
{
staticFn();
cout << "this is fn()
";
}
void staticFn()
{
cout << "this is staticFn()
";
}
连接时,将产生找不到函数staticFn()定义的错误。
B、主意事项
在文件作用域下声明的inline函数默认为static类型。
二、面象对象中的static关键字(主要指类中的static关键字)
1、静态数据成员
特点:
A、内存分配:在程序的全局数据区分配。
B、初始化和定义:
a、静态数据成员定义时要分配空间,所以不能在类声明中定义。
b、为了避免在多个使用该类的源文件中,对其重复定义,所在,不能在类的头文件中
定义。
c、静态数据成员因为程序一开始运行就必需存在,所以其初始化的最佳位置在类的内部实现。
C、特点
a、对相于 public,protected,private 关键字的影响它和普通数据成员一样,
b、因为其空间在全局数据区分配,属于所有本类的对象共享,所以,它不属于特定的类对象,在没产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。
D、访问形式
a、 类对象名.静态数据成员名
b、 类类型名:: 静态数据成员名
E、静态数据成员,主要用在类的所有实例都拥有的属性上。比如,对于一个存款类,帐号相对 于每个实例都是不同的,但每个实例的利息是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局区的内存,所以节省存贮空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了,因为它们实际上是共用一个东西。
2、静态成员函数
特点:
A、静态成员函数与类相联系,不与类的对象相联系。
B、静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实例。
作用:
主要用于对静态数据成员的操作。
调用形式:
A、类对象名.静态成员函数名()
B、类类型名:: 静态成员函数名()
shellhy_cn 于01 : 15 发表 已被浏览305次 评论(1) / 引用(193)
静态全局变量 [回复]
我在编译器上试过,确实如你所说那样。原因是static int n;这条语句。n虽然是静态全局变量,但它的作用域
只在file2,所以在file1中访问它当然不行!
2004年10月28日
#
模拟键盘平时不是很常用, 但是当调用某些快捷键执行某项功能时, 它真的是那么的方便呀. 你不信? 看看下面的实现, 你就会大呼: 为什么不早点告诉我? 呵呵, 原来没有blog呀, 都靠这些挣分呢.
1) 显示桌面:
很多软件有显示桌面的功能, 并且大家的方法都是遍历窗口, 然后让它们最小化, 其实 win系统给咱们了一个非常方便的WIN键(就是键盘上在CTRL键和ALT键之间的那个带win标志的按键), 利用它, 可以轻松的完成显示桌面的功能.
keybd_event(VK_LWIN, 0, 0 ,0);
keybd_event('M', 0, 0 ,0);
keybd_event('M', 0, KEYEVENTF_KEYUP ,0);
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP,0);
其他的操作也类似, 比如直接显示开始的运行,就把上面的'M'换成'R'即可。
直接 keybd_event(VK_LWIN, 0, 0 ,0);
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP,0);
直接显示“开始”对话框了。
2) 实现快速的全选
很多的时候,比如listctrl实现全选,你可以用listctrl循环设置每一项的状态为选中,多罗索的事情呀。用快捷键试一试CTRL+A,其他的快捷键一样的用法,呵呵,你知道怎么办了吧?
keybd_event(VK_CONTROL, (BYTE)0, 0 ,0);
keybd_event('A',(BYTE)0, 0 ,0); //此处可以用 'A', (BYTE)65, 用'a'不起作用.
keybd_event('A', (BYTE)0, KEYEVENTF_KEYUP,0);
keybd_event(VK_CONTROL, (BYTE)0, KEYEVENTF_KEYUP,0);
3) 执行某些特殊的键,比如数字键,大小写,下面是数字键的例子
bool bState=true; //true为按下NumLock,false反之
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if( (bState && !(keyState[VK_NUMLOCK] & 1)) ||
(!bState && (keyState[VK_NUMLOCK] & 1)) )
{
// Simulate a key press
keybd_event( VK_NUMLOCK,
0x45,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
// Simulate a key release
keybd_event( VK_NUMLOCK,
0x45,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
}
4) 你想CTRL+ALT+DELETE三键一起按下,
keybd_event(VK_CONTROL, 0, 0 ,0);
keybd_event(VK_MENU,0, 0 ,0);
keybd_event(VK_DELETE,0, 0 ,0);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP ,0);
keybd_event(VK_MENU,0, KEYEVENTF_KEYUP ,0);
keybd_event(VK_DELETE,0, KEYEVENTF_KEYUP ,0);
呵呵,这样不会成功呀,因为这几个键直接是操作系统来截获执行的,而模拟键盘只能发向应用程序,所以这种方法不行的(想显示锁定对话框,用 LockWorkStation();)
5) Window2000/NT/XP已经不提倡用这个函数了,上面的方法只是为了让大家开阔一下思路,怎么替代呢,呵呵,看下面,所以上面的所有代码都可以用这个来完成
//2000下用这个代替 ,包含 "winable.h"
INPUT input[4];
memset(input, 0, sizeof(input));
input[0].type = input[1].type = input[2].type = input[3].type = INPUT_KEYBOARD;
input[0].ki.wVk = input[3].ki.wVk = VK_LWIN;
input[1].ki.wVk = input[2].ki.wVk = 'R';
//接下来释放它,这一点很重要。
input[2].ki.dwFlags = input[3].ki.dwFlags = KEYEVENTF_KEYUP;
input[0].ki.time = input[1].ki.time = input[2].ki.time = input[3].ki.time = GetTickCount();
SendInput(4, input, sizeof(INPUT));
感觉比那个有点罗索,呵呵。
====================
附WIN键的部分快捷键:
WIN键+D=快速的切到桌面,再次点击返回
WIN键+E=快速打开资源管理器
WIN键+R=“运行”。
WIN键+M=全部视窗最小化。
WIN键+Shift+M=取消全部视窗最小化。
WIN键+F1=Help。
WIN键+F=“寻找”。
WIN键+Ctrl+F=显示“查找电脑”。
WIN键+Tab=切换工作列的程式。
WIN键+Break=显示系统内容。
2004年10月27日
#
我在学习VC,或者在阅读别人写的文章的时候,偶尔碰到下面很多有趣的,并且很奇怪的语句,整理起来,以备后忘. 其实有些是不大容易想到的技巧,贴出来权当大伙饭后没事的小品文,当然不要过多的看重类似的语句学习,而忽略了基础知识。
一. 奇怪的宏定义
(1) #define for if(0); else for
按照c++标准,for中定义的变量的作用域应该只在for循环中有效,而VC却不行,比如这样定义是不对的
for(int i=0;i<90;i++)
{
...;
}
for(int i=0;i<90;i++) //重复定义i变量
{
...;
}
如果加上标题的那句,那么就可以了,就是让i作用域局限在else中. 这个问题在net中已经得到解决。
二、宏定义怪圈
#define wait_event(wq,condition) \
do{ \
if(condition) \
break; \
__wait_event(wq,condition); \
}while(0)
明明这句话只执行一次,为什么还还用do-while语句呢?
假设有这样一个宏定义
#define macro(condition) \
if(condition) dosomething();
现在在程序中这样使用这个宏:
if(temp)
macro(i);
else
doanotherthing();
一切看起来很正常,但是仔细想想。这个宏会展开成:
if(temp)
if(condition) dosomething();
else
doanotherthing();
这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。为了避免这个错误,我们使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。
这个用法在linux源码中很常见。
三、功能强大的解释
除了/* */和 //解释以外,你见过这样的解释方法了吗?
#if(0)
........
#endif
这样是为了解释掉某段程序,而不影响其中的/*...*/的作用,便于调试,而/*.....*/是不能嵌套的,编译会出错.
四、数组变脸 a[i]和i[a]
在程序里本应该用a[i],但i[a]竟然和a[i]输出的结果一样。为什么。今天把问题整理如下:
i[a]是标准语法。“[]”称为下标运算符,其语法为:
postfix_expression [ expression ]
其中“postfix_expression”和“expression”之中必须有一个是指针类型(或数组),而另一个是整型。
例如下面的程序是完全合法的:
int a[]={0,1,2,3,4};
printf("%d\n",3[a]);
下标运算符参与的表达式在求解时仅仅是做一个变换而已,将“postfix_expression [ expression ]”
改写为“ * ( postfix_expression + expression ) ”,因此a[3]和3[a]分别改写为*(a+3)和*(3+a),
可见二者是完全等价的。但注意不要用i[a]这种形式,因为它不符合日常习惯。
实验代码:
#include "stdafx.h"
#include "iostream.h"
int f();
int main(int argc, char* argv[])
{
int a[20]={1,2,3,4,5,6,7,8,9};
cout<<a[f()]<<endl;
cout<<f()[a]<<endl;
return 0;
}
int f()
{
return 4;
}
实验结果:
4
4
Press any key to continue
五、双胞胎定义和声明:int x;x;
这儿是个关于宏的问题,我曾用过ATL的串转换宏,包括W2A,开始有些东西我还不太明白。为了使用这些宏,必须在函数的开始处用USES_CONVERSION来初始化某些局部变量。用就用吧,但是看看这个宏的定义,它有类似下面的代码:
// 在atlconv.h文件中
#define USES_CONVERSION \
int _convert; _convert; \
UINT _acp = GetACP(); _acp; \
LPCWSTR _lpw; _lpw; \
LPCSTR _lpa; _lpa
为什么它们用“int x;x;”——这种后面跟着变量的声明?
很多人都碰到过这个令人困惑的问题,后来发现简单的答案是:禁止编译器的警告信息(warning)。如果单独有一行代码:
int x;
且从来没有使用过x,那么编译器汇报错“unreferenced local variable:x”,意思是未引用过的局部变量x,如果将警告信息的输出
调到最大。为了避免讨厌的警告,USES_CONVERSION引用声明的变量。
int x; // 声明
x; // 使用这个变量
在C++之前的时代,程序员有时在C中用函数形参做同样的事情来避免“unreferenced formal parameter”或其它的深奥费解的编译错误。
void MyFunc(int x, char y)
{
x;
y;
…
}
当然,现在用下面的代码可以更有效地完成同样的事情:
// 参数 x 不是用
void MyFunc(int /* x */)
{
…
}
近期很多兄弟们问怎么样打包程序,如何获取所需dll的信息,这就需要使用VC所带的Depends软件,该软件在VC6安装目录下的tools文件夹里面 D:\Microsoft Visual Studio\Common\Tools,直接
双击执行,然后打开exe文件即可,它主要有下面几个注意事项:
1)所编的软件所需的Dll文件,可以得到相应的Dll路径,版本,属性等。
2)窗口分四部分:
左上角是Dll信息窗口,显示你程序所需的Dll模块,
右边第一个窗口是所选的Dll模块所使用的函数,
右边第二个窗口是所选Dll模块的所有的导出函数,
下面窗口是所有需要的Dll模块的属性
3)右边两个窗口出现四个标签:序号,提示,函数,入口点
如果利用导出是函数,那么出现函数名,如果导出的是序号,那么函数项就是N/A(无法显示)
出现红色提示表示不正常,一般为没有该导出函数
4)该工具得到的是你软件中隐式链接的Dll库,也就是用lib关联的Dll模块,
无法显示显式链接的Dll模块,也就是用LoadLibrary函数导入的Dll函数。(切记切记!)
5)无法提供Borland C++ Builder所提供的Dll文件,无法提供vxd软件的调用
程序调试过程中,最重要也罗嗦的就是要查看变量的值,还有GetLastError要时时执行看API执行
是否正确,下面的高效的使用watch窗口可以给各位减轻一下调试的劳动:
在watch窗口中输入下面的内容:
1) @err,hr 显示API函数调用GetLastError的返回值,和解释
2) @eax,hr 显示eax寄存器的值,由于win的API的返回值放在eax中,所以这句话就是得到最近一个API 的返回值
3) p,***(数字) 数组指针扩展出来只有单个元素,而你又想看到全部数组元素,可以用这个技巧
4) VC调试观察窗口的格式化符号表格
符号 格式 例子 输出
d或者i 有符号十进制整数 -42,d -42
U 无符号十进制整数 42,d 42
O 无符号八进制整数 42,o 052
x或X 十六进制整数 42,x 0x0000002a或0x0000002A
H 为d,I,u,o,x显示前缀 42,hx 0X002a
F 有符号浮点数 1.5,f 1.500000
E 有符号科学计数法 1.5,e 1.500000e+000
G 压缩的有符号浮点数 1.5,g 1.5
C 字符 42,c '*'
S ANSI字符串 "bugs",s "bugs"
Su Unicode字符串 "bugs",st "bugs"
Hr HRESULT和Win32错误码 0X06,hr The handle is invalid
wm Windows消息号 0x01,wm WM_CREATE
[digits] 显示数组元素 s,5 显示s[]前五个值
很简单吧,你调试的过程中不妨试一试,事半功倍的效果........