我的C++的几个小例子,希望对大家有用

Meteor_Code 2009-06-23 10:51:10
刚来这个论坛,写下一点关于c++,特别是用VC开发时使用的小例子,以纠正网上的许多不全面的东西.希望对各位有用.


1

//++什么是引用,不懂变长参数列表的看不懂

#include "stdio.h"

int iasd = 8;

void fun(int& prei,unsigned int ul)
{
printf("\n*prei:%x", *((int*)(*((&ul) - 1))));
printf("\nprei:%x", *((&ul) - 1));
}

main()
{
printf("\n&iasd:%x",&iasd);
fun(iasd,0);
getchar();
return 0;
}



//--什么是引用,不懂变长参数列表的看不懂

程序就不讲解了,什么是引用类型,也许很多人都想过,今天我告诉你,引用类型的变量在内存里其实就是这个变量所引用原变量的指针.



2

//++operator new,operator new[],operator delete,operator delete[],不懂c++和脑子进水者看不明白


#include "stdio.h"
#include "malloc.h"

#define DELETE_OTHER_STYLE 0
#define NEW_RETURN_ZERO 0

class CNewAndDeleteTest
{
public:
long m_lTestData;
CNewAndDeleteTest();
~CNewAndDeleteTest();
public:
void *operator new(size_t sizeLength);
void *operator new[](size_t sizeLength);
void operator delete(void *pSpace);
void operator delete[](void *pSpace);
#if (DELETE_OTHER_STYLE != 0)
void operator delete(void *pSpace, size_t sizeLength);
#endif
};

CNewAndDeleteTest::CNewAndDeleteTest()
{
m_lTestData = 12345;
printf("\nCNewAndDeleteTest::CNewAndDeleteTest()");
}

CNewAndDeleteTest::~CNewAndDeleteTest()
{
m_lTestData = 54321;
printf("\nCNewAndDeleteTest::~CNewAndDeleteTest()");
}

void *CNewAndDeleteTest::operator new(size_t sizeLength)
{
printf("\nCNewAndDeleteTest::operator new(size_t sizeLength):%ld",sizeLength);
#if (NEW_RETURN_ZERO != 0)
return 0;
#else
return malloc(sizeLength);
#endif
}

void *CNewAndDeleteTest::operator new[](size_t sizeLength)
{
printf("\nCNewAndDeleteTest::operator new[](size_t sizeLength):%ld",sizeLength);
#if (NEW_RETURN_ZERO != 0)
return 0;
#else
return malloc(sizeLength);
#endif
}

void CNewAndDeleteTest::operator delete[](void *pSpace)
{
printf("\nCNewAndDeleteTest::operator delete[](void *pSpace)");
free(pSpace);
return;
}

#if (DELETE_OTHER_STYLE != 0)
void CNewAndDeleteTest::operator delete(void *pSpace, size_t sizeLength);
{
printf("\nCNewAndDeleteTest::operator delete(void *pSpace, size_t sizeLength):%ld",sizeLength);
free(pSpace);
return;
}
#endif

void CNewAndDeleteTest::operator delete(void *pSpace)
{
printf("\nCNewAndDeleteTest::operator delete(void *pSpace)");
free(pSpace);
return;
}


main()
{
long i,num = 3;
CNewAndDeleteTest *pobjTest;
printf("\nArr");
pobjTest = new CNewAndDeleteTest[num];
printf("\npobjTest:%x",pobjTest);
for(i = 0; i < num; i++)
{
printf("\npobjTest[%ld]:%x",i,&pobjTest[i]);
}
delete []pobjTest;
printf("\nSig");
pobjTest = new CNewAndDeleteTest;
printf("\npobjTest:%x",pobjTest);
delete pobjTest;
getchar();
return 0;
}


#define NEW_DELETE_FUN_ANNOUNCE(CLASS) \
public:\
void *operator new(size_t sizeLength);\
void *operator new[](size_t sizeLength);\
void operator delete(void *pSpace);\
void operator delete[](void *pSpace);

#define NEW_DELETE_FUN_DEFINE(CLASS) \
void *CLASS::operator new(size_t sizeLength){return GetMemSpace((long)sizeLength);}\
void *CLASS::operator new[](size_t sizeLength){return GetMemSpace((long)sizeLength);}\
void CLASS::operator delete(void *pSpace){FreeMemSpace(pSpace); return;}\
void CLASS::operator delete[](void *pSpace){FreeMemSpace(pSpace); return;}

#define NEW_DELETE_FUN_DEFINE_WITH_MEM_FUN(CLASS,ALLOC,FREE) \
void *CLASS::operator new(size_t sizeLength){return ALLOC((long)sizeLength);}\
void *CLASS::operator new[](size_t sizeLength){return ALLOC((long)sizeLength);}\
void CLASS::operator delete(void *pSpace){FREE(pSpace); return;}\
void CLASS::operator delete[](void *pSpace){FREE(pSpace); return;}


//--operator new,operator new[],operator delete,operator delete[],不懂c++和脑子进水者看不明白



这个有点长,主要是明确以下重载一个class的operator new,operator new[],operator delete,operator delete[]这四个特殊操作符函数使用的函数原形,注意开关DELETE_OTHER_STYLE 引出的函数,这个函数在VC里是不支持的,但在其他编译软件里是否支持我就不知道了.还有,如果你的operator new,operator new[]函数只是返回0指针的话,那么你要建立的新对象不会建立.在重载时operator new,operator new[]函数的责任只是分配空间,分配多少由参数决定,而delete,operator delete[]只负责删除空间,要删除那段空间由参数指针指出,这些函数是在你使用delete,new时自动调用,参数生成过程由编译器生成,在程序执行时自动使用.还有一点,在VC中new[]函数的参数永远比你使用new[]操作符时指定的结构数量多一个,我个人认为这是为了兼容BASIC这种数组索引从1开始而不是0的语言.

NEW_DELETE_FUN_ANNOUNCE

NEW_DELETE_FUN_DEFINE

NEW_DELETE_FUN_DEFINE_WITH_MEM_FUN

三个宏是我写的,他们用来声明和实现operator new,operator new[],operator delete,operator delete[]四个函数的,第一个用来声明,后面两个用来定义,NEW_DELETE_FUN_DEFINE使用STL里的内存函数,而NEW_DELETE_FUN_DEFINE_WITH_MEM_FUN使用你自己指定的内存函数来实现.

还有:千万不要试图重载全局的operator new,operator new[],operator delete,operator delete[]函数,因为你可能造成巨大的错误,有很多编译器根本不允许你重载全局的.



3

//++什么是进程或者实例句柄

#include "windows.h"
#include "stdio.h"

main()
{
char name[300];
HINSTANCE hIns;
memset(name,0,300);
GetModuleFileName(0,name,300);
hIns = ::GetModuleHandle(0);
printf("\n%x->%s",hIns, name);
printf("\n%s",hIns);
getchar();
return 0;
}

#include "stdio.h"

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//......
{
char carr[20];
sprintf(carr, "%x", hInstance);
MessageBox(0,carr,0,0);
}
//......
}

//--什么是进程或者实例句柄

实例句柄是WIN32程序的一个概念.

自己运行一下你就知道了,实例句柄其实就是你程序文件内存镜象开始处的指针,至少NT中MS是这么做的,而且在VC6中EXE的永远是0x40000,后面具体几个0忘了,不是4个就是5个.



4

//++三种调用方式的栈变化,内嵌C的汇编语言

//必须在DEBUG下使用,以防RELEASE做代码化简.忽略所有执行时的错误

#include "stdio.h"

long __cdecl testfun_cdecl(long a)
{
printf("\nin:%ld addr:%08x", a, &a);
return a;
}

long __stdcall testfun_stdcall(long a)
{
printf("\nin:%ld addr:%08x", a, &a);
return a;
}

long testfun_cpp(long a) //c/cpp调用方式
{
printf("\nin:%ld addr:%08x", a, &a);
return a;
}

void stacktest()
{
long li;
li = 3;//防止编译的时候被pass掉,所以对变量做一些操作,li--也是这个意思;
printf("\n%x", &li);
li--;
}

typedef long (__cdecl *CDECL_CALL_TEST_FUN)(long);
typedef long (__stdcall *STDCALL_CALL_TEST_FUN)(long);
typedef long (*CPP_CALL_TEST_FUN)(long);

CDECL_CALL_TEST_FUN pcdeclfun;
STDCALL_CALL_TEST_FUN pstdcallfun;
CPP_CALL_TEST_FUN pcppfun;


main()
{

unsigned long ulEsp;
ulEsp = 1;
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
testfun_stdcall(1);
stacktest();
testfun_stdcall(1);
stacktest();
testfun_cdecl(2);
stacktest();
testfun_cdecl(2);
stacktest();
testfun_cpp(3);
stacktest();
testfun_cpp(3);
stacktest();

printf("\ntestfun_stdcall");
pcdeclfun = (CDECL_CALL_TEST_FUN)testfun_stdcall;
pstdcallfun = (STDCALL_CALL_TEST_FUN)testfun_stdcall;
pcppfun = (CPP_CALL_TEST_FUN)testfun_stdcall;

__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcdeclfun(1);printf(" pcdeclfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pstdcallfun(1);printf(" pstdcallfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcppfun(1);printf(" pcppfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);

printf("\ntestfun_cdecl");
pcdeclfun = (CDECL_CALL_TEST_FUN)testfun_cdecl;
pstdcallfun = (STDCALL_CALL_TEST_FUN)testfun_cdecl;
pcppfun = (CPP_CALL_TEST_FUN)testfun_cdecl;

__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcdeclfun(2);printf(" pcdeclfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pstdcallfun(2);printf(" pstdcallfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcppfun(2);printf(" pcppfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);

printf("\ntestfun_cpp");
pcdeclfun = (CDECL_CALL_TEST_FUN)testfun_cpp;
pstdcallfun = (STDCALL_CALL_TEST_FUN)testfun_cpp;
pcppfun = (CPP_CALL_TEST_FUN)testfun_cpp;

__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcdeclfun(3);printf(" pcdeclfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pstdcallfun(3);printf(" pstdcallfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcppfun(3);printf(" pcppfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);

printf("\n");
getchar();
return 0;
}

/***************************

esp:12ff2c
in:1 addr:0012ff28
12ff20
in:1 addr:0012ff28
12ff20
in:2 addr:0012ff28
12ff20
in:2 addr:0012ff28
12ff20
in:3 addr:0012ff28
12ff20
in:3 addr:0012ff28
12ff20

testfun_stdcall
esp:12ff2c
in:1 addr:0012ff28 pcdeclfun
esp:12ff30
in:1 addr:0012ff2c pstdcallfun
esp:12ff30
in:1 addr:0012ff2c pcppfun
esp:12ff34

testfun_cdecl
esp:12ff34
in:2 addr:0012ff30 pcdeclfun
esp:12ff34
in:2 addr:0012ff30 pstdcallfun
esp:12ff30
in:2 addr:0012ff2c pcppfun
esp:12ff30

testfun_cpp
esp:12ff30
in:3 addr:0012ff2c pcdeclfun
esp:12ff30
in:3 addr:0012ff2c pstdcallfun
esp:12ff2c
in:3 addr:0012ff28 pcppfun
esp:12ff2c

***************************/

//--三种调用方式的栈变化



这是VC下的程序,其他环境汇编关键字可能不是__asm

后面有输出结果,只有调用前后的esp值相同的才是这个函数真正的调用形式,这个例子主要是为了后面的一个.



...全文
139 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
linshuqiang 2010-12-26
  • 打赏
  • 举报
回复
楼主能不能讲解一下第一个引用程序,不太理解。多多感谢~~~
henny123 2009-06-23
  • 打赏
  • 举报
回复
学习啦
henny123 2009-06-23
  • 打赏
  • 举报
回复
学习啦
mm6688 2009-06-23
  • 打赏
  • 举报
回复
我终于发现我很水。。。因为我看见了很多星星
zhgfzhgf212 2009-06-23
  • 打赏
  • 举报
回复
顶一下,菜鸟学习中……
Meteor_Code 2009-06-23
  • 打赏
  • 举报
回复
5

//++dllimport和dllemport调用方式的栈变化,内嵌C的汇编语言

//DLL文件代码.DLL可以使用RELEASE的.

#include "windows.h"
#include "stdio.h"

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

extern "C" long __declspec(dllexport) test_dll_call(long a)
{
printf("\ntest_dll_call:%ld addr:%x", a, &a);
return a;
}

//end

//EXE必须在DEBUG下使用,以防RELEASE做代码化简.忽略所有执行时的错误
//动态引入方式

#include "windows.h"
#include "stdio.h"

typedef long (__cdecl *CDECL_CALL_TEST_FUN)(long);
typedef long (__stdcall *STDCALL_CALL_TEST_FUN)(long);
typedef long (*CPP_CALL_TEST_FUN)(long);

CDECL_CALL_TEST_FUN pcdeclfun;
STDCALL_CALL_TEST_FUN pstdcallfun;
CPP_CALL_TEST_FUN pcppfun;

main()
{
HMODULE hmou;
void *pfun;
unsigned long ulEsp;

hmou=LoadLibrary("dllscall.dll");
if(0 == hmou)
{
printf("\nLoadLibrary error!");
}
else
{
pfun = (void*)GetProcAddress(hmou,"test_dll_call");
if(0 == pfun)
{
printf("\nGetProcAddress error!");
FreeLibrary(hmou);
}
else
{
pcdeclfun = (CDECL_CALL_TEST_FUN)pfun;
pstdcallfun = (STDCALL_CALL_TEST_FUN)pfun;
pcppfun = (CPP_CALL_TEST_FUN)pfun;

__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcdeclfun(1);printf(" pcdeclfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pstdcallfun(2);printf(" pstdcallfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcppfun(3);printf(" pcppfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
}
}
printf("\n");
getchar();
FreeLibrary(hmou);
return 0;
}

/***************************

esp:12ff24
test_dll_call:1 addr:12ff20 pcdeclfun
esp:12ff24
test_dll_call:2 addr:12ff20 pstdcallfun
esp:12ff20
test_dll_call:3 addr:12ff1c pcppfun
esp:12ff20

***************************/

//end

//静态引入方式

#include "windows.h"
#include "stdio.h"

#pragma comment(lib, "dllscall.lib")

typedef long (__cdecl *CDECL_CALL_TEST_FUN)(long);
typedef long (__stdcall *STDCALL_CALL_TEST_FUN)(long);
typedef long (*CPP_CALL_TEST_FUN)(long);

CDECL_CALL_TEST_FUN pcdeclfun;
STDCALL_CALL_TEST_FUN pstdcallfun;
CPP_CALL_TEST_FUN pcppfun;

extern "C" long __declspec(dllimport) test_dll_call(long a);

main()
{
unsigned long ulEsp;

pcdeclfun = (CDECL_CALL_TEST_FUN)test_dll_call;
pstdcallfun = (STDCALL_CALL_TEST_FUN)test_dll_call;
pcppfun = (CPP_CALL_TEST_FUN)test_dll_call;

__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcdeclfun(1);printf(" pcdeclfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pstdcallfun(2);printf(" pstdcallfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);
pcppfun(3);printf(" pcppfun");
__asm {mov ulEsp, esp} printf("\nesp:%x",ulEsp);

printf("\n");

getchar();
return 0;
}

/****************************

esp:12ff2c
test_dll_call:1 addr:12ff28 pcdeclfun
esp:12ff2c
test_dll_call:2 addr:12ff28 pstdcallfun
esp:12ff28
test_dll_call:3 addr:12ff24 pcppfun
esp:12ff28

****************************/

//end

//--dllimport和dllemport调用方式的栈变化,内嵌C的汇编语言



注意dllimport和dllemport声明的函数其实是形式cdecl调用,而WIN32API的库是stdcall调用,这个要十分注意,否则你会造成严重的栈溢出错误!!!



OVER

64,439

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧