当前位置:首页 » 操作系统 » visualc源码

visualc源码

发布时间: 2023-01-20 18:05:12

① 如何在Visual Studio2005中直接编译c源代码

新建=>项目=>Visual C++项目=>Win32控制台应用程序=>(输入名字)=>应用程序设置=>空项目=>源文件=>添加(不是菜单栏里的,是右边的解决方案视图里的)=>现有项=>添加已经有了的以C为扩展名的C文件=>(菜单栏)调试=>启动调试就行了(直接按F5也行)
为了看到程序运行结果,请包含头文件#include <stdlib.h>,请在程序末加一句system("pause");

② 怎样用Microsoft visual c++把c源代码编译成exe 可执行文件

调试
-->
生成解决方案.
如果没有建立工程的话,
那么先-
新建-
控制台项目
-
空的项目.
然后给项目
-
添加文件.
然后
调试
-->
生成解决方案.
基本步骤就是这样,
具体VC版本不同文字会略有差别,
基本上一样.

③ 如何在Visual C++ 6.0调试多源代码C程序!

装上c语言考试系统,抽一道题,打开考生文件夹,会看到里面有三个
.c
文件。。tk.c
error.c
和program.c,那分别是填空题,改错题,和编程题地源程序,把他们用vc++6.0程序打开,就能看到源代码,然后修改代码,编译,连接,运行
c++6.0只是用来调试程序的~

④ 怎样用Microsoft visual c++把c源代码编译成exe 可执行文件

以VC6举例:

1、打开电脑上安装的vc6.0,进入如图界面

⑤ C 语言源代码在Microsoft Visual C++ 6.0 中运行怎么操作

哪来这么麻烦,直接用创建一个文本文件,把代码放进去保存,然后把这个文本文件的扩展名“.txt”改为“.cpp”,然后用vc打开。(打开方法也很多:1如果你的系统.cpp格式的文件关联了vc,直接双击就能打开;2.打开vc界面,上面有个“open”,然后找到这个文件打开它),接下来就可以编译和调试

⑥ VC 6.0的C语言库函数的源代码可以在哪找到

深入printf
/***
*printf.c - print formatted
*
* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines printf() - print formatted data
*
*******************************************************************************/

#include
#include
#include
#include
#include
#include
#include

/***
*int printf(format, ...) - print formatted data
*
*Purpose:
* Prints formatted data on stdout using the format string to
* format data and getting as many arguments as called for
* Uses temporary buffering to improve efficiency.
* _output does the real work here
*
*Entry:
* char *format - format string to control data format/number of arguments
* followed by list of arguments, number and type controlled by
* format string
*
*Exit:
* returns number of characters printed
*
*Exceptions:
*
*******************************************************************************/

int __cdecl printf (
const char *format,
...
)
/*
* stdout ''PRINT'', ''F''ormatted
*/
{
va_list arglist;
int buffing;
int retval;

va_start(arglist, format);

_ASSERTE(format != NULL);//断言宏。如果输出格式字符串指针为空,则在DEBUG版下断言,报告错误。

_lock_str2(1, stdout);

buffing = _stbuf(stdout);//stdout:指定输出到屏幕

retval = _output(stdout,format,arglist);

_ftbuf(buffing, stdout);

_unlock_str2(1, stdout);

return(retval);
}
以上为printf()的源代码
1、从含有可选参数函数中获得可选参数,以及操作这些参数
typedef char *va_list;
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
假定函数含有一个必选参数和多个可选参数,必选参数声明为普通数据类型,且能通过参数名来获得该变量的值。可选参数通过宏va_start、va_arg和va_end(定义在stdarg.h或varargs.h中)来进行操作,即通过设置指向第一个可选参数指针、返回当前参数、在返回参数后重新设置指针来操作所有的可选参数。
va_start:为获取可变数目参数的函数的参数提供一种便捷手段。设置arg_ptr为指向传给函数参数列表中的第一个可选参数的指针,且该参数必须是va_list类型。prev_param是在参数列表中第一个可选参数前的必选参数。
va_arg:返回由arg_ptr所指向的参数的值,且自增指向下一个参数的地址。type为当前参数的类型,用来计算该参数的长度,确定下一个参数的起始位置。它可以在函数中应用多次,直到得到函数的所有参数为止,但必须在宏va_start后面调用。
va_end:在获取所有的参数后,设置指针arg_ptr为NULL。
下面举例说明:
#include
#include
int average( int first, ... );
void main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );

/* Call with 4 integers. */
printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );

/* Call with just -1 terminator. */
printf( "Average is: %d\n", average( -1 ) );
}

int average( int first, ... )
{
int count = 0, sum = 0, i = first;
va_list marker;

va_start( marker, first ); /* Initialize variable arguments. */
while( i != -1 )
{
sum += i;
count++;
i = va_arg( marker, int);
}
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
返回值为:
Average is: 3
Average is: 8
Average is: 0
综上所述,在printf()函数中,可以只输出一个字符串,也可按照一定的形式输出含有多个可选参数的字符串信息。因此,首先就要通过这些宏来获取所有的可选参数。在上面的源码可以看出printf()中,只使用了宏at_start,将可选参数的首地址赋给了arglist。
2、锁定字符串及输出字符串到屏幕
#define _lock_str2(i,s) _lock_file2(i,s)
void __cdecl _lock_file2(int, void *);
#define _unlock_str2(i,s) _unlock_file2(i,s)
void __cdecl _unlock_file2(int, void *);
int __cdecl _stbuf(FILE *);
void __cdecl _ftbuf(int, FILE *);
int __cdecl _output(FILE *, const char *, va_list);
在output函数中,读取格式字符串中的每一个字符,然后对其进行处理,处理方式根据每一个字符所代表的意义来进行,如:普通字符直接利用函数WRITE_CHAR(ch, &charsout);输出到控制台。
其中的主要部分是对转换说明符(d,c,s,f)的处理,现在将对其中的部分代码进行详细说明,这里只说明最基本的转换说明符,对这些须基本的转换说明符进行修饰的修饰符,程序中单独进行处理。下面是函数output()(output.c)部分源代码:
case ST_TYPE:
//表示当前处理的字符的类型为转换说明符。
...
switch (ch) {
//下面对参数的获取都是利用宏va_arg( va_list arg_ptr, type );来进行的。
case ''c'': {
//从参数表中获取单个字符,输出到缓冲字符串中,此时,type=int
buffer[0] = (char) get_int_arg(&argptr); /* get char to print */
text = buffer;
textlen = 1; /* print just a single character */
}
break;

case ''s'': {
//从参数表中获取字符串,输出到缓冲字符串中,此时,type=char*
int i;
char *p; /* temps */
text = get_ptr_arg(&argptr);
...
}
break;

case ''w'': {
//对宽字符进行处理
...
} /* case ''w'' */
break;
...
case ''e'':
case ''f'':
case ''g'': {
//对浮点数进行操作
...
#if !LONGDOUBLE_IS_DOUBLE
/* do the conversion */
if (flags & FL_LONGDOUBLE) {
_cldcvt((LONGDOUBLE*)argptr, text, ch, precision, capexp);
va_arg(argptr, LONGDOUBLE);
//对长双精度型进行处理,此时,type=long double
}
else
#endif /* !LONGDOUBLE_IS_DOUBLE */
{

//对双精度型进行处理,此时,type=double
_cfltcvt((DOUBLE*)argptr, text, ch, precision, capexp);
va_arg(argptr, DOUBLE);
}
...
break;
//对整型变量处理
case ''d'':
case ''i'':
...
goto COMMON_INT;

case ''u'':
radix = 10;
goto COMMON_INT;

case ''p'':
...
goto COMMON_INT;

case ''o'':
...

注:对于浮点型double和long double,有相应的转换说明符(%f表示双精度型,%lf表示长双精度型),而float却没有。其中的原因是,在K&RC下,float值用于表达式或用作参数前,会自动转换成double类型。而ANSI C一般不会自动把float转换成double。有些程序已假定其中的float参数会被转换成double,为了保护大量这样的程序,所有printf()函数的float参数还是被自动转换成double型。因此,在K&RC或ANSI C下,都无需用特定的转换说明符来显示float型。
综上所述,转换说明符必须与待打印字符的类型。通常,用户有种选择。例如,如要打印一个int类型的值。则只可以使用%d,%x或%o。所有这些说明符都表示要打印一个int类型的值;它们只不过提供了一个数值的几种不同表示。类似一,可以用%f、%g和%e来表示double类型的值。但如果转换说明与类型不匹配,将会出现意想不到的结果。为什么呢?问题就在于C向函数传递信息的方式。
这个失败的根本细节与具体实现相关。它决定了系统中的参数以何方式传递。函数调用如下:
float n1;
double n2;
long n3;
long n4;
...
printf("%ld,%ld,%ld,%ld",n1,n2,n3,n4);
这个调用告诉计算机,要把变量n1,n2,n3和n4的值交给计算机,它把这些变量放进称作栈(stack)的内存区域中,来完成这一任务。计算机把这些值放进栈中,其根据是变量的类型而不是转换说明符,比如n1,把8个字节放入栈中(float被转换成double),类似地,为n2放了8字节,其后给n3和n4各放了4个字节。接着,控制的对象转移到printf();此函数从栈中读数,不过在这一过程中,它是在转换说明符的指导下,读取数值的。说明符%ld指定printf()应读4个字节(va_arg( va_list arg_ptr, type )中type=long),因此printf()读入栈中的4个字节,作为它的第一个值。但是这只是n1的前半部分,这个值被看成一个long整数。下一个说明符%ld读入4个字节,这正是n1的后半部分,这个值被看成第二个long整数。类似地,第三、第四次又读入n2的前后两部分。因此,尽管我们对n3和n4使用了正确的说明符,printf()仍然会产生错误。

这里也可以下载
http://mirrors.kernel.org/gnu/glibc/glibc-2.7.tar.gz

⑦ 怎样在visual C++中建立一个C源程序

1、首选先打开c++编程软件,打开之后会有提示,不用管它,关闭就可以了。

⑧ Visual Studio 2019怎么编译C语言源程序

1、首先,打开C语言编辑器工具,然后在该工具中编写程序的源代码,如下图所示,然后进入下一步。

⑨ 如何看c语言标准库函数的源代码

1、首先标准只是规定了这些函数的接口和具体的运行效率的要求,这些函数具体是怎么写得要看各个编译器的实现和平台。

2、例如使用的编译器是visual studio,微软提供了一部分C运行时(CRT)的源码,里面会有memcpy,strcpy之类的函数的实现,在visual studio 2005下的路径是C:Program FilesMicrosoft Visual Studio 8VCcrtsrc。

⑩ 用什么软件来查看一个用Microsoft Visual C++ 6.0 编写的程序的源代码

标 题: MFC逆向初级研究(1)
作 者: 北斗之摇光
时 间: 2007-03-15 17:14
链 接: http://bbs.pediy.com/showthread.php?t=41087
详细信息:

【文章标题】: MFC逆向初级研究(1)
【文章作者】: 北斗之摇光
【作者邮箱】: [email protected]
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
引言
本文主要针对微软的VC++6.0中使用MFC产生的EXE文件的逆向研究,我曾经使用微软的Visual Studio 2005编译了一
个EXE文件,通过IDA反汇编以后发现该文件与VC++6.0产生的文件还是有所区别,因此特别在此声明一下。文中主要使用了I
DA pro 5.0和在看雪(www.pediy.com)下载的OllyICE作为工具对目标文件进行反汇编。在此也感谢看雪论坛的各位的无私奉
献,在研究过程的中的困难多通过各位的帖子得到了帮助。
逆向的关键
我认为逆向的关键主要是要弄明白目标文件的算法和实现过程,在Window操作系统下,软件的实现过程就体现在其
对Window消息的处理,而软件的算法则包含在处理的具体过程中。对于通过SDK编写的"传统"的Windows应用程序基本都具备
几个共同的特征:WinMain函数、WinProc函数、窗口注册、消息循环。对于这类目标文件的分析主要集中的WinProc的分析上
,WinProc的函数地址获得一般是通过窗口注册函数中的参数获得。(由于我对于这类文件没有具体逆向过,所以只是大概的
说说,有不对的地方请各位不要客气,尽管拍砖)
而使用MFC(Microsoft Function Class)顾名思义,该类库主要封装了大部分的Windows API函数所以在代码中看
不到原本的SDK编程中的消息循环、窗口过程函数等等东西,所有这些封装在相应的mfcxx.dll中,让程序员能够专着与处理
过程与算法。这种做法于逆向而言有好处也有坏处:
坏处就是加大了对于MFC产生的EXE文件的逆向难度,让许多的和我一样的菜鸟迷失在汇编代码中找不找北了,基本主要就靠
猜测实现过程中用到了那些函数,然后对文件导入表的函数下断点来寻找我们所需要的处理过程;
好处就是这样的做法使得EXE文件中主要都是目标程序的Window消息处理流程以及算法,而且dll中的大部分函数的功能都能
在MSDN中查到。如果能够通过对目标文件的分析得到这个Window消息处理流程和算法架构,基本上我们就可以重写整个软件;
要做到上面的目标,首先我们要对MFC有所了解,推荐没有基础的兄弟们读读候俊杰的《深入浅出MFC》。该书在逆向过
程中完全可以作为一本参考书,让你能通过源代码了解实现过程,网上有很多该书的电子版下载。
一个逆向MFC产生的EXE文件的例子
下面我们就通过一个具体的例子来学习一下如何从目标文件中挖到我们需要的东西。首先我们来产生一个需要的EXE文件。
在此我假定各位对MFC有过一定的使用经验,毕竟逆向分析才是本文的重点。
1.产生例子所需要的目标文件:
我们通过VC++6.0的向导来产生一个名为ReverseMFC的工程,这个工程的设置情况如下:
Application type of fff:
Dialog-Based Application targeting:
Win32
Classes to be created:
Application: CFffApp in ReverseMFC.h and ReverseMFC.cpp
Dialog: CFffDlg in ReverseMFCDlg.h and ReverseMFCDlg.cpp
Features:
+ Uses shared DLL implementation (MFC42.DLL)
+ Localizable text in:
中文[中国]
直接编译以后就能够运行,为了确定我们是否正确的分析的整个目标文件,在该对话框中加入一个我们自定义的按钮如
下,对于该按钮的处理函数如下设定为:
AfxMessageBox("I find it!",MB_OK);编译后就得到了我们需要的目标文件。
现在我们得到了所需要的目标文件,在IDA中载入该文件。在此我们最好是产生Release版本的EXE文件,毕竟所有的发
布软件都是Release版本的。
2.具体分析
在IDA中按Ctrl+S找到.rdata段,该段主要存储了目标文件的类运行时创建信息、MessageMap信息、MessageEntry信息、
虚函数表、RTTI数据(如果编译选项中选择了支持RTTI的话)。
在到达.rdata段后我们可以看到这样的代码,对数据进行格式转换后可以得到如下图所示的数据。
.rdata:004021C0 ; 屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯?
.rdata:004021C0
.rdata:004021C0 ; Segment type: Pure data
.rdata:004021C0 ; Segment permissions: Read
.rdata:004021C0 _rdata segment para public 'DATA' use32
.rdata:004021C0 assume cs:_rdata
.rdata:004021C0 ;org 4021C0h
.rdata:004021C0 off_4021C0 dd offset sub_401000 ; DATA XREF: sub_401010o
.rdata:004021C4 dd offset dword_4021C8
.rdata:004021C8 dword_4021C8 dd 111h ; DATA XREF: .rdata:004021C4o
.rdata:004021CC dd 0
.rdata:004021D0 dd 0E146h
.rdata:004021D4 dd 0E146h
.rdata:004021D8 dd 0Ch
.rdata:004021DC dd offset CWinApp::OnHelp(void)
.rdata:004021E0 dd 0
.rdata:004021E4 dd 0
.rdata:004021E8 dd 0
.rdata:004021EC dd 0
.rdata:004021F0 dd 0
.rdata:004021F4 dd 0
.rdata:004021F8 off_4021F8 dd offset CWinApp::GetRuntimeClass(void)
.rdata:004021F8 ; DATA XREF: unknown_libname_1-56o
.rdata:004021FC dd offset sub_401040
.rdata:00402200 dd offset nullsub_2
.rdata:00402204 dd offset nullsub_3
.rdata:00402208 dd offset nullsub_2
.rdata:0040220C dd offset CCmdTarget::OnCmdMsg(uint,int,void *,AFX_CMDHANDLERINFO *)
其中的off_4021C0就是一个MessageMap数据;dword_4021C8就是MessageMap所指的MessageEntry数据;off_4021F8就是一个
类的虚函数表的开始位置。那么具体这些数据时那个类的相关数据呢?如此判断的依据是什么?
首先我们知道MessageEntry是的数据结构定义如下,而且以6个0表示整个数组的结束。
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
因此我们有理由假设"dword_4021C8就是MessageMap所指的MessageEntry数据"。
而MessageMap数据结构定义如下:
struct AFX_MSGMAP
{
#ifdef _AFXDLL
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
#else
const AFX_MSGMAP* pBaseMap;
#endif
const AFX_MSGMAP_ENTRY* lpEntries;
};
off_4021C0的两个数据中第二个数据恰恰就是我们前面假设为MessageEntry的指针,跟入其第一个数据,我们看到如下的代
码:
.text:00401000 ; *************** S U B R O U T I N E ***************************************
.text:00401000
.text:00401000
.text:00401000 sub_401000 proc near ; DATA XREF: .rdata:off_4021C0o
.text:00401000 mov eax, ds:AFX_MSGMAP const CWinApp::messageMap
.text:00401005 retn
.text:00401005
.text:00401005 sub_401000 endp
恰恰是一个返回基类的MessageMap的函数。因此我们也同样有理由假设"off_4021C0就是一个MessageMap数据"。
对于虚函数表的假设是如何被证明呢?首先我们要知道关于虚函数表的一点知识:虚函数表由虚函数的地址组成,表中函数
地址的顺序和它们第一次出现的顺序(即在类定义的顺序)一致。若有重载的函数,则替换掉基类函数的地址。通过这个我
们可以知道MFC中虚函数表中的函数顺序必然是先按照CObject->CCmdtarget->。。。。这个类继承顺序中的虚函数顺序来处
理虚函数表中的函数顺序的。只要证明这个我们"假设的虚函数"中的函数顺序与上面提到的知识相符合则有理由说明我们的
假设成立。
首先来看CObject中虚函数的顺序,在查看CObject的声明文件后得到了这个类的虚函数顺序:
virtual CRuntimeClass* GetRuntimeClass() const;
virtual ~CObject(); // virtual destructors are necessary
virtual void Serialize(CArchive& ar);
#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
再来查看CCmdtarget的虚函数顺序,在查看CObject的声明文件后得到了这个类的虚函数顺序:
DECLARE_DYNAMIC(CCmdTarget);
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo);
#ifndef _AFX_NO_OLE_SUPPORT
// called when last OLE reference is released
virtual void OnFinalRelease();
#endif
#ifndef _AFX_NO_OLE_SUPPORT
// called before dispatching to an automation handler function
virtual BOOL IsInvokeAllowed(DISPID dispid);
virtual BOOL GetDispatchIID(IID* pIID);
virtual UINT GetTypeInfoCount();
virtual CTypeLibCache* GetTypeLibCache();
virtual HRESULT GetTypeLib(LCID lcid, LPTYPELIB* ppTypeLib);
之所以还要列出"DECLARE_DYNAMIC(CCmdTarget);"是因为这个宏的定义如下:
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static const AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
这个virtual CRuntimeClass* GetRuntimeClass() const; 覆盖掉了一开始的CObject的相对应函数。依次按照类的顺序对
照下来,就可以知道该表确实是虚函数表。同时,对应的GetMessageMap虚函数的位置上跟入后,可以得到如下代码:
.text:00401010 ; *************** S U B R O U T I N E ***************************************
.text:00401010
.text:00401010
.text:00401010 sub_401010 proc near ; DATA XREF: .rdata:00402228o
.text:00401010 mov eax, offset off_4021C0
.text:00401015 retn
.text:00401015
.text:00401015 sub_401010 endp

恰恰是返回了我们之前假设的MessageMap的地址。

--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

热点内容
ntp服务器怎么搭建 发布:2025-07-05 02:51:53 浏览:770
谭浩强c语言基础 发布:2025-07-05 02:51:45 浏览:776
外地卡密码忘了怎么办 发布:2025-07-05 02:50:10 浏览:186
电脑配置点评怎么选 发布:2025-07-05 02:39:23 浏览:1002
如何配置与锌反应的稀硫酸 发布:2025-07-05 02:39:20 浏览:937
php分割文件 发布:2025-07-05 02:22:15 浏览:478
sql平均成绩语句 发布:2025-07-05 02:11:41 浏览:277
java脱机 发布:2025-07-05 02:11:35 浏览:66
php变量赋值给变量 发布:2025-07-05 02:10:56 浏览:558
javaequals方法 发布:2025-07-05 01:57:23 浏览:98