您的位置:首页 > 编程语言 > C语言/C++

puts "Hello world" in VC++

2011-09-01 18:09 423 查看
本文所需的文件下载

http://download.csdn.net/source/3567384

我们现在做一件经典的事情,输出一行Hello world.

假设给你一台电脑和一个windows操作系统,然后什么都没装,你每次能安装一个程序,我们来看看能够做什么。

1.首先,你获得了记事本, Notepad.exe, 你输入了一行

output a string Hello world

现在你觉得output a string这个名字太长了,而Hello world和前面的混了。到底是output 'a string Hello world' 还是 output a string 'Hello world'呢?

你换了一下描述,缩写了一下,加了括号显得比较专业,于是成了

puts("Hello world");


保存为了C:\mydir\hello.cpp

(假定你新建了mydir这个目录)

[现在C:\mydir有hello.cpp一个文件]

2.现在你没法真正意义上的运行这句话,虽然你看到了Hello world的文字。

所以你要了VC++的编译器cl.exe,这里是VC2008下的, 以及相关的依赖dll(c1.dll,c1xx.dll,c2.dll,2052/clui.dll,mspdb80.dll)

假设你好在有一些命令行经验,如果没有,你打开了cmd,进入了C:\mydir( 输入C:回车 cd\mydir回车 )

然后你运行了

cl hello.cpp

现在CL给出了很奇怪的提示

hello.cpp(1) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int

hello.cpp(1) : error C2440: “初始化”: 无法从“const char [12]”转换为“int” 没有使该转换得以执行的上下文

是什么意思呢。

这时候,某人告诉你说,光是一行命令是不够的,C语言还要有函数,于是你加了好看的花边:

void work()
{
puts("Hello world");
}


这个时候

cl hello.cpp

提示说

hello.cpp(3) : error C3861: “puts”: 找不到标识符

[现在C:\mydir的文件是 hello.cpp cl.exe c1.dll c1xx.dll c2.dll 2052目录下的clui.dll mspdb80.dll]

3.既然这样,于是你想说明一下我有一个puts,通过查询手册,你加了puts的说明或声明:

看上去是这个样子的

int puts( const char * );
void work() { puts("Hello world"); }


于是
cl hello.cpp

提示说

cl: 命令行 error D8027 :无法执行“link.exe”

[现在C:\mydir的文件是 hello.cpp cl.exe c1.dll c1xx.dll c2.dll 2052目录下的clui.dll mspdb80.dll link.exe hello.obj]

4.于是你又要来了link.exe

cl hello.cpp

于是link提示说

/out:hello.exe

hello.obj

LINK : fatal error LNK1104: 无法打开文件“LIBCMT.lib”

不巧的是,你不能一次要求整个VC++,压缩包也不行,所以你选择了看LINK的帮助,并最终发现一个可能有关的选项:

/nodefaultlib

同时你学会了从cl向link传送选项的方法

/link

cl hello.cpp /link /nodefaultlib

然后link又提示说,必须定义入口点,本着缺哪里补哪里的精神,那就定义一个入口点。

由于我们刚才写的是work,所以入口名字就叫work了,puts这行代码是不算入口点也没有记号来表示它的。

然后link又提示说缺少子系统定义,那也定义一个。因为只是输出,没有窗口,可以就用console

于是我们最终的命令行是:

cl hello.cpp /link /nodefaultlib /entry:work /subsystem:console

现在link提示说

/out:hello.exe

/nodefaultlib

/entry:work

/subsystem:console

hello.obj

hello.obj : error LNK2019: 无法解析的外部符号 "int __cdecl puts(char const *)" (

?puts@@YAHPBD@Z),该符号在函数 "void __cdecl work(void)" (?work@@YAXXZ) 中被引用

hello.exe : fatal error LNK1120: 1 个无法解析的外部命令

[现在C:\mydir的文件是 hello.cpp cl.exe c1.dll c1xx.dll c2.dll 2052目录下的clui.dll mspdb80.dll link.exe ]

5.因为提示说是外部符号,那么改这里可能是没用的。

事实上puts位于msvcrt.dll中,于是你又谷歌了一下,要来了lib.exe

新建了一个msvcrt.def文件,只写了哪里有函数和需要的函数名是哪个

LIBRARY msvcrt
EXPORTS
puts


然后你运行

lib /def:msvcrt.def

我的32位编译器在这里有一行警告,提示没有指定机器形式,默认生成了x86文件

这时候生成了一个msvcrt.lib和一个msvcrt.exp

[现在C:\mydir的文件是 hello.cpp cl.exe c1.dll c1xx.dll c2.dll 2052目录下的clui.dll mspdb80.dll link.exe lib.exe msvcrt.def msvcrt.lib msvcrt.exp hello.obj]

6.现在把生成的文件传给link,你会发现这里只要msvcrt.lib就够了。

cl hello.cpp /link msvcrt.lib /nodefaultlib /subsystem:console /entry:work

还是出现了问题

/out:hello.exe

msvcrt.lib

/nodefaultlib

/subsystem:windows

/entry:work

hello.obj

hello.obj : error LNK2019: unresolved external symbol "int __cdecl puts(char con

st *)" (?puts@@YAHPBD@Z) referenced in function "void __cdecl work(void)" (?work

@@YAXXZ)

hello.exe : fatal error LNK1120: 1 unresolved externals

这里要注意的是,我们为了时髦,扩展名用了cpp而不是c,那么cl会当作c++程序来编译hello.cpp。

然而你不幸被告知puts在msvcrt.dll中是c程序编译的,所以有必要在你的hello.cpp里面修改一下。

extern "C"{
int puts(const char *);
}
void work() { puts("Hello world"); }


然后运行

cl hello.cpp /link msvcrt.lib /nodefaultlib /subsystem:console /entry:work

用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 15.00.21022.08 版

版权所有(C) Microsoft Corporation。保留所有权利。

hello.cpp

Microsoft (R) Incremental Linker Version 9.00.21022.08

Copyright (C) Microsoft Corporation. All rights reserved.

/out:hello.exe

msvcrt.lib

/nodefaultlib

/subsystem:console

/entry:work

hello.obj

似乎没有提示错误,键入hello.exe

Hello world

看,你成功了

[现在C:\mydir的文件是 hello.cpp cl.exe c1.dll c1xx.dll c2.dll 2052目录下的clui.dll mspdb80.dll link.exe lib.exe msvcrt.def msvcrt.lib msvcrt.exp hello.obj hello.exe]

7.这就是这个经典例子的精简重现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: