博文

C语言可变参数函数的实现(2008-03-02 21:19:00)

摘要:// 下文转自网络 C语言可变参数函数的实现 一、什么是可变参数 我们在C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的(用三个点“…”做参数占位符),实际调用时可以有以下的形式: printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s", i, s);    以上这些东西已为大家所熟悉。但是究竟如何写可变参数的C函数以及这些可变参数的函数编译器是如何实现,这个问题却一直困扰了我好久。本文就这个问题进行一些探讨,希望能对大家有些帮助. 二、写一个简单的可变参数的C函数 先看例子程序。该函数至少有一个整数参数,其后占位符…,表示后面参数的个数不定. 在这个例子里,所有的输入参数必须都是整数,函数的功能只是打印所有参数的值. 函数代码如下: //示例代码1:可变参数函数的使用 #i nclude "stdio.h" #i nclude "stdarg.h" void simple_va_fun(int start, ...) {     va_list arg_ptr;     int nArgValue =start;     int nArgCout=0;     //可变参数的数目     va_start(arg_ptr,start); //以固定参数的地址为起点确定变参的内存起始地址。     do     {         ++nArgCout;         printf("the %d th arg: % d\n",nArgCout,nArgValue......

阅读全文(2229) | 评论:0

#pragma pack(n)作用(2008-01-18 16:09:00)

摘要:通过#pragma pack(n)改变C编译器的字节对齐方式
在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。

     例如,下面的结构各成员空间分配情况:
struct test
{
     char x1;
     short x2;
     float x3;
     char x4;
};
     结构的第一个成员x1,其偏移地址为0,占据了第1个字节。第二个成员x2为short类型,其起始地址必须2字节对界,因此,编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上,在它们前面不需要额外的填充字节。在test结构中,成员x3要求4字节对界,是该结构所有成员中要求的最大对界单元,因而test结构的自然对界条件为4字节,编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。更改C编译器的缺省字节对齐方式
     在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变缺省的对界条件:
  · 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
     · 使用伪指令#pragma pack (),取消自定义字节对齐方式。

     另外,还有如下的一种方式:
     · __attribute((aligned (n))),让所作用的......

阅读全文(4601) | 评论:0

使用 ACCESS 时遇到的恼火问题(2008-01-01 22:21:00)

摘要:
使用 ACCESS 时遇到的恼火问题 这几天做毕业设计,是与ACCESS 数据库有关的, 因为是刚开始测试,所以手动在ACCESS里输入一些数据,但是当我想输入"CObject" 时却莫明其妙的变成了"Cobject", 如下图: 我试了其它一些单词发现有的变了,有的没变,当时很恼火,差点没骂ACCESS设计者的老祖宗,最后在输入时出现了一个闪电图标,点了下才知道是"自动更正"把我的输入自动给改了,为什么拿我当白痴,改了我的输入后不给半点提示 !!! 类似的好像WORD里也有这个功能,我觉得这些功能完全没有必要,毕竟用户不是白痴,当今软件功能都非常强,并不是每个用户都会在使用前不厌其烦的翻你那厚厚的用户手册,个人认为类似的功能要么就不要提供,如果定要提供也要默认禁用.......

阅读全文(2814) | 评论:0

在DLL中使用资源(2007-12-20 17:08:00)

摘要:在DLL中使用资源( 此文系网络转载 )        在CSDN论坛上最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题。这里我们从Win32 DLL和MFC DLL两个方面来分析并解决这个问题。 1.Win32 DLL        在Win32 DLL中使用对话框很简单,你只需要在你的DLL中添加对话框资源,而且可以在对话框上面设置你所需要的控件。然后使用DialogBox或者CreateDialog这两个函数(或相同作用的其它函数)来创建对话框,并定义你自己的对话框回调函数处理对话框收到的消息。下面通过一个具体实例来学习如何在Win32 DLL中使用对话框,可以按照以下步骤来完成这个例子:   1)在VC菜单中File->New新建一个命名为UseDlg的Win32 Dynamic-Link Library工程,下一步选择A simple DLL project。   2)在VC菜单中Insert->Resource添加一个ID为IDD_DLG_SHOW的Dialog资源,将此Dialog上的Cancel按钮去掉,仅保留OK按钮。再添加一个ID为IDD_ABOUTBOX的对话框,其Caption为About。保存此资源,将资源文件命名为UseDlg.rc。并将resource.h和UseDlg.rc加入到工程里面。   3)在UseDlg.app中包含resource.h,并添加如下代码:   HINSTANCE hinst = NULL; HWND hwndDLG = NULL;   BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); BOOL CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); extern "C" __declspec(dllexport) void ShowDlg()......

阅读全文(2109) | 评论:0

COleVariant 类(2007-12-17 22:48:00)

摘要:
function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}  VARIANT、COleVariant 和_variant_t      (转)  在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:

struct tagVARIANT {
 VARTYPE vt;
 union {
  short iVal; // VT_I2.
  long lVal; // VT_I4.
  float fltVal; // VT_R4.
  double dblVal; // VT_R8.
  DATE date; // VT_DATE.
  BSTR bstrVal; // VT_BSTR.
  …
  short * piVal; // VT_BYREF|VT_I2.
  long * plVal; // VT_BYREF|VT_I4.
  float * pfltVal; // VT_BYREF|VT_R4.
  double * pdblVal; // VT_BYREF|VT_R8.
  DATE * pdate; // V......

阅读全文(3771) | 评论:0

匈牙利命名法前缀(2007-12-17 20:33:00)

摘要:匈牙利命名法(转载)   匈牙利命名法虽然是C++所使用的,但WIN32ADA与它也紧密关联. 前缀 含义 a   array                                                      数组 b bool(int)                                                布尔 by Unsigned char                                         无符号字符(字节) c Char                                                   ......

阅读全文(4935) | 评论:0

C语言宏定义使用技巧(2007-12-05 21:52:00)

摘要: 该文系网络搜集:   C语言宏定义使用技巧 2007-12-03 18:33 写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等。下面列举一些成熟软件中常用得宏定义。。。。。。 1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDEF_H   //头文件内容 #endif 2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。 typedef  unsigned char      boolean;     /* Boolean value type. */ typedef  unsigned long int  uint32;      /* Unsigned 32 bit value */ typedef  unsigned short     uint16;      /* Unsigned 16 bit value */ typedef  unsigned char      uint8;       /* Unsigned 8  bit value */ typedef  signed long int    int32;       /* Signed 32 bit value */ typedef  signed short      ......

阅读全文(7239) | 评论:1

工作集问题(退出码)(2007-12-04 21:55:00)

摘要:工作集问题 #define   _WIN32_WINNT   0x0500
#include <windows.h>
#include <assert.h> int main(){
 // 创建一个进程
 TCHAR szPath[80]=TEXT("E:\\MFC\\codeSave\\snake\\Rel\\snake.exe");
 STARTUPINFO st = {sizeof(st)};
 PROCESS_INFORMATION pInfo;
 CreateProcess(NULL,szPath,NULL,NULL,
  FALSE,CREATE_SUSPENDED,NULL,NULL,&st,&pInfo);  // 创建一个工作集
 HANDLE hJob = CreateJobObject(NULL,TEXT("deng"));
 
 // 进程加入工作集
 AssignProcessToJobObject(hJob,pInfo.hProcess);
 
 // 唤醒进程的主线程
 ResumeThread(pInfo.hThread);  _getch();
 // 结束工作集
 DWORD dwExitCodeSet = 100;
 TerminateJobObject(hJob,dwExitCodeSet);
 
 // 测试退出码
 DWORD dwExitCode;
 //GetExitCodeProcess(pInfo.hThread,&dwExitCode);
 GetExitCodeProcess(pInfo.hProcess,&dwExitCode);  assert(dwExitCode==dwExitCodeSet);  retu......

阅读全文(2559) | 评论:0

不明所以的程序(C++析构函数)(2007-12-03 16:42:00)

摘要:不明所以的程序 请看下面的代码: #include <iostream>
using namespace std; class Test{
public:
    Test(){ cout<<this<<" construct\n"; }
    ~Test(){ cout<<this<<" deastruct\n"; }
}; Test global;
int main(){
    Test local;
    cout<<"local variable: "<<&local<<endl;
    cout<<"global variable: "<<&global<<endl;
    return EXIT_SUCCESS;
} /// 输出结果如下 0047CDF8 construct
0012FF70 construct
local variable: 0012FF70
global variable: 0047CDF8
0012FF70 deastruct
Press any key to continue 从输出结果可以知道全局变量的析构函数没有被调用 再看下面的代码: #include <iostream>
using namespace std; class Test{
public:
    Test(){ printf("%x construct\n",this); }
    ~Test(){ printf("%x deastruct\n",this); }
}; Test global;
int main(){
    Test local;
&nbs......

阅读全文(2576) | 评论:0

有关线程函数 GetExitCodeThread()和ExitThread()(2007-12-02 11:27:00)

摘要:有关线程函数 GetExitCodeThread() 和 ExitThread()    看了侯捷翻译的 <<Win32 多线程程序设计>>,觉得他在翻译这两个函数的时候好象有点和实际不符,我没有该书的原版,不知道是翻译的问题还是原书的问题。 函数: GetExitCodeThread() 功能: 获取一个结束线程的返回值 函数原形: BOOL GetExitCodeThread( HANDLE hThread,  LPDWORD lpExitCode); 参数: hThread 指向欲获取返回值的线程对象的句柄                lpExitCode 用于存储线程的返回值 返回值:函数执行成功则返回非0值,否则返回 0(FALSE) IN MSDN: Remarks If the specified thread has not terminated, the termination status returned is STILL_ACTIVE. If the thread has terminated, the termination status returned may be one of the following: The exit value specified in the ExitThread or TerminateThread function. The return value from the thread function. The exit value of the thread's process. Warning  If a thread happens to return STILL_ACTIVE (259) as an error code, applications that test for this value could end up in an infinite loop 最后一句: 如果一个线程将 STILL_ACTIVE 作为错......

阅读全文(16866) | 评论:3