当前位置:文档之家› C语言库函数制作方法

C语言库函数制作方法

动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内汽车工厂

Linux下创建库函数(共享库)(含动态调用)详解

本文档主要参考Program Library HOWTO,作者是luster(hwang@https://www.doczj.com/doc/c39835034.html,),任何非商业目的的再次发行本文档都是允许的,但是请保留作者信息和本版权声明。本文档首先在https://www.doczj.com/doc/c39835034.html,发布。

1. 介绍

使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他的程序使用。程序函数库可以使整个程序更加模块化,更容易重新编译,而且更方便升级。程序函数库可分为3种类型:静态函数库(static libraries)、共享函数库(shared libraries)和动态加载函数库(dynamically loaded libraries)。

静态函数库是在程序执行前就加入到目标程序中去了;而共享函数库则是在程序启动的时候加载到程序中,它可以被不同的程序共享;动态加载函数库则可以在程序运行的任何时候动态的加载。实际上,动态函数库并非另外一种库函数格式,区别是动态加载函数库是如何被程序员使用的。后面我们将举例说明。

2. 静态函数库

静态函数库实际上就是简单的一个普通的目标文件的集合,一般来说习惯用“.a”作为文件的后缀。可以用ar这个程序来产生静态函数库文件。Ar 是archiver的缩写。静态函数库现在已经不在像以前用得那么多了,主要是共享函数库与之相比较有很多的优势的原因。慢慢地,大家都喜欢使用共享函数库了。

不过,在一些场所静态函数库仍然在使用,一来是保持一些与以前某些程序的兼容,二来它描述起来也比较简单。

静态库函数允许程序员把程序link起来而不用重新编译代码,节省了重新编译代码的时间。不过,在今天这么快速的计算机面前,一般的程序的重新编译也花费不了多少时间,所以这个优势已经不是像它以前那么明显了。静态函数库对开发者来说还是很有用的,例如你想把自己提供的函数给别人使用,但是又想对函数的源代码进行保密,你就可以给别人提供一个静态函数库文件。理论上说,使用ELF格式的静态库函数生成的代码可以比使用共享函数库(或者动态函数库)的程序运行速度上快一些,大概1-5%。

创建一个静态函数库文件,或者往一个已经存在地静态函数库文件添加新的

目标代码,可以用下面的命令:

ar rcs my_library.a file1.o file2.o

这个例子中是把目标代码file1.o和file2.o加入到my_library.a这个函数库文件中,如果my_library.a不存在则创建一个新的文件。在用ar命令创建静态库函数的时候,还有其他一些可以选择的参数,可以参考ar的使用帮助。这里不再赘述。

一旦你创建了一个静态函数库,你可以使用它了。你可以把它作为你编译和连接过程中的一部分用来生成你的可执行代码。如果你用gcc来编译产生可执行代码的话,你可以用“-l”参数来指定这个库函数。你也可以用ld来做,使用它的“-l”和“-L”参数选项。具体用法,可以参考info:gcc。

3. 共享函数库

共享函数库中的函数是在当一个可执行程序在启动的时候被加载。如果一个共享函数库正常安装,所有的程序在重新运行的时候都可以自动加载最新的函数库中的函数。对于Linux系统还有更多的可以实现的功能:

o 升级了函数库但是仍然允许程序使用老版本的函数库。

o 当执行某个特定程序的时候可以覆盖某个特定的库或者库中指定的函数。 o 可以在库函数被使用的过程中修改这些函数库。

3.1. 一些约定

如果你要编写的共享函数库支持所有有用的特性,你在编写的过程中必须遵循一系列约定。你必须理解库的不同的名字间的区别,例如它的“soname”和“real name”之间的区别和它们是如何相互作用的。你同样还要知道你应该把这些库函数放在你文件系统的什么位置等等。下面我们具体看看这些问题。

3.1.1. 共享库的命名

每个共享函数库都有个特殊的名字,称作“soname”。Soname名字命名必须以“lib”作为前缀,然后是函数库的名字,然后是“.so”,最后是版本号信息。不过有个特例,就是非常底层的C库函数都不是以lib开头这样命名的。

每个共享函数库都有一个真正的名字(“real name”),它是包含真正库函数代码的文件。真名有一个主版本号,和一个发行版本号。最后一个发行版本号是可选的,可以没有。主版本号和发行版本号使你可以知道你到底是安装了什么版本的库函数。

另外,还有一个名字是编译器编译的时候需要的函数库的名字,这个名字就是简单的soname名字,而不包含任何版本号信息。

管理共享函数库的关键是区分好这些名字。当可执行程序需要在自己的程序中列出这些他们需要的共享库函数的时候,它只要用soname就可以了;反过来,当你要创建一个新的共享函数库的时候,你要指定一个特定的文件名,其中包含很细节的版本信息。当你安装一个新版本的函数库的时候,你只要先将这些函数库文件拷贝到一些特定的目录中,运行ldconfig就可以。Ldconfig检查已经存在的库文件,然后创建soname的符号链接到真正的函数库,同时设置/etc/ld.so.cache这个缓冲文件。这个我们稍后再讨论。

Ldconfig并不设置链接的名字,通常的做法是在安装过程中完成这个链接名字的建立,一般来说这个符号链接就简单的指向最新的soname 或者最新版本的函数库文件。最好把这个符号链接指向soname,因为通常当你升级你的库函数的后,你就可以自动使用新版本的函数库勒。

我们来举例看看:

/usr/lib/libreadline.so.3 是一个完全的完整的soname,ldconfig可以设置一个符号链接到其他某个真正的函数库文件,例如是/usr/lib/libreadline.so.3.0。同时还必须有一个链接名字,例如/usr/lib/libreadline.so 就是一个符号链接指向/usr/lib/libreadline.so.3。

3.1.2. 文件系统中函数库文件的位置

共享函数库文件必须放在一些特定的目录里,这样通过系统的环境变量设置,应用程序才能正确的使用这些函数库。大部分的源码开发的程序都遵循 GNU 的一些标准,我们可以看info帮助文件获得相信的说明,info信息的位置是:info: standards#Directory_Variables。GNU标准建议所有的函数库文件都放在/usr/local/lib目录下,而且建议命令可执行程序都放在/usr/local/bin目录下。这都是一些习惯问题,可以改变的。

文件系统层次化标准FHS(Filesystem Hierarchy Standard)(https://www.doczj.com/doc/c39835034.html,/fhs)规定了在一个发行包中大部分的函数库文件应该安装到/usr/lib目录下,但是如果某些库是在系统启动的时候要加载的,则放到/lib目录下,而那些不是系统本身一部分的库则放到/usr/local/lib下面。

上面两个路径的不同并没有本质的冲突。GNU提出的标准主要对于开发者开发源码的,而FHS的建议则是针对发行版本的路径的。具体的位置信息可以看/etc/ld.so.conf里面的配置信息。

3.2. 这些函数库如何使用

在基于GNU glibc的系统里,包括所有的linux系统,启动一个ELF格式的

二进制可执行文件会自动启动和运行一个program loader。对于Linux系统,这个loader的名字是/lib/ld-linux.so.X(X是版本号)。这个loader启动后,反过来就会 load所有的其他本程序要使用的共享函数库。

到底在哪些目录里查找共享函数库呢?这些定义缺省的是放在/etc/ld.so.conf文件里面,我们可以修改这个文件,加入我们自己的一些特殊的路径要求。大多数RedHat系列的发行包的/etc/ld.so.conf文件里面不包括/usr/local/lib这个目录,如果没有这个目录的话,我们可以修改/etc/ld.so.conf,自己手动加上这个条目。

如果你想覆盖某个库中的一些函数,用自己的函数替换它们,同时保留该库中其他的函数的话,你可以在/etc/ld.so.preload中加入你想要替换的库(.o 结尾的文件),这些preloading的库函数将有优先加载的权利。

当程序启动的时候搜索所有的目录显然会效率很低,于是Linux系统实际上用的是一个高速缓冲的做法。Ldconfig缺省情况下读出 /etc/ld.so.conf相关信息,然后设置适当地符号链接,然后写一个cache到/etc/ld.so.cache这个文件中,而这个 /etc/ld.so.cache则可以被其他程序有效的使用了。这样的做法可以大大提高访问函数库的速度。这就要求每次新增加一个动态加载的函数库的时候,就要运行ldconfig来更新这个cache,如果要删除某个函数库,或者某个函数库的路径修改了,都要重新运行ldconfig来更新这个 cache。通常的一些包管理器在安装一个新的函数库的时候就要运行ldconfig。

另外,FreeBSD使用cache的文件不一样。FreeBSD的ELF cache是/var/run/ld-elf.so.hints,而a.out的cache则是/var/run/ld.so.hints。它们同样是通过ldconfig来更新。

3.3. 环境变量

各种各样的环境变量控制着一些关键的过程。例如你可以临时为你特定的程序的一次执行指定一个不同的函数库。Linux系统中,通常变量LD_LIBRARY_PATH就是可以用来指定函数库查找路径的,而且这个路径通常是在查找标准的路径之前查找。这个是很有用的,特别是在调试一个新的函数库的时候,或者在特殊的场合使用一个非标准的函数库的时候。环境变量LD_PRELOAD 列出了所有共享函数库中需要优先加载的库文件,功能和 /etc/ld.so.preload 类似。这些都是有/lib/ld-linux.so这个loader来实现的。值得一提的是,LD_LIBRARY_PATH可以在大部分的UNIX-linke系统下正常起作用,但是并非所有的系统下都可以使用,例如HP-UX系统下,就是用 SHLIB_PATH这个变量,而在AIX下则使用LIBPATH这个变量。

LD_LIBRARY_PATH在开发和调试过程中经常大量使用,但是不应该被一个普通用户在安装过程中被安装程序修改,大家可以去参考https://www.doczj.com/doc/c39835034.html,/~barr/ldpath.html,这里有一个文档专门介绍为什么不使用LD_LIBRARY_PATH这个变量。

事实上还有更多的环境变量影响着程序的调入过程,它们的名字通常就是以LD_或者RTLD_打头。大部分这些环境变量的使用的文档都是不全,通常搞得人头昏眼花的,如果要真正弄清楚它们的用法,最好去读loader的源码(也就是gcc的一部分)。

允许用户控制动态链接函数库将涉及到setuid/setgid这个函数如果特殊的功能需要的话。因此,GNU loader通常限制或者忽略用户对这些变量使用setuid和setgid。如果loader通过判断程序的相关环境变量判断程序的是否使用了 setuid或者setgid,如果uid和euid不同,或者gid和egid部一样,那么loader就假定程序已经使用了setuid或者 setgid,然后就大大的限制器控制这个老链接的权限。如果阅读GNU glibc的库函数源码,就可以清楚地看到这一点,特别的我们可以看elf/rtld.c和sysdeps/generic/dl-sysdep.c这两个文件。这就意味着如果你使得uid和gid与euid和egid分别相等,然后调用一个程序,那么这些变量就可以完全起效。

3.4. 创建一个共享函数库

现在我们开始学习如何创建一个共享函数库。其实创建一个共享函数库非常容易。首先创建object文件,这个文件将加入通过gcc –fPIC 参数命令加入到共享函数库里面。PIC的意思是“位置无关代码”(Position Independent Code)。下面是一个标准的格式:

gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list

下面再给一个例子,它创建两个object文件(a.o和b.o),然后创建一个包含a.o和b.o的共享函数库。例子中”-g”和“-Wall”参数不是必须的。

gcc -fPIC -g -c -Wall a.c

gcc -fPIC -g -c -Wall b.c

gcc -shared -Wl,-soname,liblusterstuff.so.1 -o liblusterstuff.so.1.0.1 a.o b.o -lc

下面是一些需要注意的地方:

·不用使用-fomit-frame-pointer这个编译参数除非你不得不这样。虽然使用了这个参数获得的函数库仍然可以使用,但是这使得调试程序几乎没有用,无法跟踪调试。

·使用-fPIC来产生代码,而不是-fpic。

·某些情况下,使用gcc 来生成object文件,需要使用“-Wl,-export-dynamic”这个选项参数。通常,动态函数库的符号表里面包含了这些动态的对象的符号。这个选项在创建ELF格式的文件时候,会将所有的符号加入到动态符号表中。可

以参考ld的帮助获得更详细的说明。

3.5. 安装和使用共享函数库

一旦你了一个共享函数库,你还需要安装它。其实简单的方法就是拷贝你的库文件到指定的标准的目录(例如/usr/lib),然后运行ldconfig。

如果你没有权限去做这件事情,例如你不能修改/usr/lib目录,那么你就只好通过修改你的环境变量来实现这些函数库的使用了。首先,你需要创建这些共享函数库;然后,设置一些必须得符号链接,特别是从soname到真正的函数库文件的符号链接,简单的方法就是运行ldconfig:

ldconfig -n directory_with_shared_libraries

然后你就可以设置你的LD_LIBRARY_PATH这个环境变量,它是一个以逗号分隔的路径的集合,这个可以用来指明共享函数库的搜索路径。例如,使用bash,就可以这样来启动一个程序my_program:

LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH my_program

如果你需要的是重载部分函数,则你就需要创建一个包含需要重载的函数的object文件,然后设置LD_PRELOAD环境变量。通常你可以很方便的升级你的函数库,如果某个API改变了,创建库的程序会改变soname。然而,如果一个函数升级了某个函数库而保持了原来的soname,你可以强行将老版本的函数库拷贝到某个位置,然后重新命名这个文件(例如使用原来的名字,然后后面加.orig 后缀),然后创建一个小的“wrapper”脚本来设置这个库函数和相关的东西。例如下面的例子:

#!/bin/sh export LD_LIBRARY_PATH=/usr/local/my_lib:$LD_LIBRARY_PATH exec

/usr/bin/my_program.orig $*

我们可以通过运行ldd来看某个程序使用的共享函数库。例如你可以看ls 这个实用工具使用的函数库:

ldd /bin/ls

libtermcap.so.2 => /lib/libtermcap.so.2 (0x4001c000)

libc.so.6 => /lib/libc.so.6 (0x40020000)

/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

通常我么可以看到一个soname的列表,包括路径。在所有的情况下,你都至少可以看到两个库:

· /lib/ld-linux.so.N(N是1或者更大,一般至少2)。

这是这个用力加载其他所有的共享库的库。

· libc.so.N(N应该大于或者等于6)。这是C语言函数库。

值得一提的是,不要在对你不信任的程序运行ldd命令。在ldd的manual 里面写得很清楚,ldd是通过设置某些特殊的环境变量(例如,对于ELF对象,设置LD_TRACE_LOADED_OBJECTS),然后运行这个程序。这样就有可能使得某地程序可能使得ldd来执行某些意想不到的代码,而产生不安全的隐患。

3.6. 不兼容的函数库

如果一个新版的函数库要和老版本的二进制的库不兼容,则soname需要改变。对于C语言,一共有4个基本的理由使得它们在二进制代码上很难兼容:

o. 一个函数的行文改变了,这样它就可能与最开始的定义不相符合。

o. 输出的数据项改变了。

o. 某些输出的函数删除了。

o. 某些输出函数的接口改变了。

如果你能避免这些地方,你就可以保持你的函数库在二进制代码上的兼容,或者说,你可以使得你的程序的应用二进制接口(ABI:Application Binary Interface)上兼容。

4. 动态加载的函数库Dynamically Loaded (DL) Libraries

动态加载的函数库Dynamically loaded (DL) libraries是一类函数库,它可以在程序运行过程中的任何时间加载。它们特别适合在函数中加载一些模块和plugin扩展模块的场合,因为它可以在当程序需要某个plugin模块时才动态的加载。例如,Pluggable Authentication Modules(PAM)系统就是用动态加载函数库来使得管理员可以配置和重新配置身份验证信息。

Linux系统下,DL函数库与其他函数库在格式上没有特殊的区别,我们前面提到过,它们创建的时候是标准的object格式。主要的区别就是这些函数库不是在程序链接的时候或者启动的时候加载,而是通过一个API来打开一个函数库,寻找符号表,处理错误和关闭函数库。通常C语言环境下,需要包含这个头文件。

Linux中使用的函数和Solaris中一样,都是dlpoen() API。当时不是所有的平台都使用同样的接口,例如HP-UX使用shlload()机制,而Windows平台用另外的其他的调用接口。如果你的目的是使得你的代码有很强的移植性,你应该使用一些wrapping函数库,这样的wrapping函数库隐藏不同的平台的接口区别。一种方法是使用glibc函数库中的对动态加载模块的支持,它使用一些潜在的动态加载函数库界面使得它们可以夸平台使用。具体可以参考https://www.doczj.com/doc/c39835034.html,/doc/API/glib/glib-dynamic-loading-of-modul es.html.

另外一个方法是使用libltdl,是GNU libtool的一部分,可以进一步参考CORBA 相关资料。

4.1. dlopen()

dlopen函数打开一个函数库然后为后面的使用做准备。C语言原形是:

void * dlopen(const char *filename, int flag);

如果文件名filename是以“/”开头,也就是使用绝对路径,那么dlopne 就直接使用它,而不去查找某些环境变量或者系统设置的函数库所在的目录了。

否则dlopen()就会按照下面的次序查找函数库文件:

1. 环境变量LD_LIBRARY指明的路径。

2. /etc/ld.so.cache中的函数库列表。

3. /lib目录,然后/usr/lib。不过一些很老的a.out的loader则是采用相反的次序,也就是先查/usr/lib,然后是/lib。

Dlopen()函数中,参数flag的值必须是RTLD_LAZY或者RTLD_NOW,RTLD_LAZY的意思是resolve undefined symbols as code from the dynamic library is executed,而RTLD_NOW的含义是resolve all undefined symbols before dlopen() returns and fail if this cannot be done'。

①RTLD_NOW:将共享库中的所有函数加载到内存

②RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数

如果有好几个函数库,它们之间有一些依赖关系的话,例如X依赖Y,那么你就要先加载那些被依赖的函数。例如先加载Y,然后加载X。

dlopen() 函数的返回值是一个句柄,然后后面的函数就通过使用这个句柄来做进一步的操作。如果打开失败dlopen()就返回一个NULL。如果一个函数库被多次打开,它会返回同样的句柄。

如果一个函数库里面有一个输出的函数名字为init,那么init就会在dlopen()这个函数返回前被执行。我们可以利用这个函数在我的函数库里面做一些初始化的工作。我们后面会继续讨论这个问题的。

4.2. dlerror()

通过调用dlerror()函数,我们可以获得最后一次调用dlopen(),dlsym(),或者dlclose()的错误信息。

4.3. dlsym()

如果你加载了一个DL函数库而不去使用当然是不可能的了,使用一个DL 函数库的最主要的一个函数就是dlsym(),这个函数在一个已经打开的函数库里面查找给定的符号。这个函数如下定义:

void * dlsym(void *handle, char *symbol);

函数中的参数handle就是由dlopen打开后返回的句柄,symbol是一个以NIL结尾的字符串。

如果dlsym()函数没有找到需要查找的symbol,则返回NULL。如果你知道某个symbol的值不可能是NULL或者0,那么就很好,你就可以根据这个返回结果判断查找的symbol是否存在了;不过,如果某个symbol的值就是NULL,那么这个判断就有问题了。标准的判断方法是先调用dlerror(),清除以前可能存在的错误,然后调用dlsym()来访问一个symbol,然后再调用dlerror()来判断是否出现了错误。一个典型的过程如下:

dlerror(); /* clear error code */

s = (actual_type) dlsym(handle, symbol_being_searched_for);

if ((err = dlerror()) != NULL)

{

/* handle error, the symbol wasn't found */

}

else

{

/* symbol found, its value is in s */

}

4.4. dlclose()

dlopen()函数的反过程就是dlclose()函数,dlclose()函数用力关闭一个DL函数库。Dl函数库维持一个资源利用的计数器,当调用dlclose的时候,就把这个计数器的计数减一,如果计数器为0,则真正的释放掉。真正释放的时候,如果函数库里面有_fini()这个函数,则自动调用_fini()这个函数,做一些必要的处理。Dlclose()返回0表示成功,其他非0值表示错误。

4.5. DL Library Example

下面是一个例子。例子中调入math函数库,然后打印2.0的余弦函数值。例子中每次都检查是否出错。应该是个不错的范例:

#include

#include

int main(int argc, char **argv)

{

void *handle;

double (*cosine)(double);

char *error;

handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);

if (!handle) {

fputs (dlerror(), stderr);

exit(1);

}

cosine = dlsym(handle, "cos");

if ((error = dlerror()) != NULL)

{

fputs(error, stderr);

exit(1);

}

printf ("%f ", (*cosine)(2.0));

dlclose(handle);

}

如果这个程序名字叫foo.c,那么用下面的命令来编译:

gcc -o foo foo.c -ldl

5. 其他

5.1. nm命令

nm命令可以列出一个函数库文件中的符号表。它对于静态的函数库和共享的函数库都起作用。对于一个给定的函数库,nm命令可以列出函数库中定义的所有符号,包括每个符号的值和类型。还可以给出在原程序中这个函数(符号)

是在多少行定义的,不过这必须要求编译该函数库的时候加“-l”选项。

关于符号的类型,这里我们再多讨论一下。符号的类型是以一个字母的形式显示的,小写字母表示这个符号是本地(local)的,而大写字母则表示这个符号是全局的(global,externel)。一般来说,类型有一下几种:T、D、B、U、W。各自的含义如下:T表示在代码段中定义的一般变量符号;D表示时初始化过的数据段;B表示初始化的数据段;U表示没有定义的,在这个库里面使用了,但是在其他库中定义的符号;W,weak的缩写,表示如果其他函数库中也有对这个符号的定义,则其他符号的定义可以覆盖这个定义。

如果你知道一个函数的名字,但是你不知道这个函数在什么库中定义的,那么可以用mn的“-o”选项和grep命令来查找库的名字。-o选项使得显示的每一行都有这个函数库文件名。例如,你要查找“cos”这个是在什么地方定义的,大致可以用下面的命令:

nm -o /lib/* /usr/lib/* /usr/lib/*/* /usr/local/lib/* 2> /dev/null

| grep 'cos$'

关于nm的更详细的用法我们可以参考info文档,位置是info:binutils#nm。

5.2. 特殊函数_init和_fini

函数库里面有两个特殊的函数,_init和_fini,这个我们在前面已经说过了。主要是分别用来初始化函数库和关闭的时候做一些必要的处理,我们可以把自己认为需要的代码放到这两个函数里面,它们分别在函数库被加载和释放的时候被执行。具体说,如果一个函数库里面有一个名字为“_init”的函数输出,那么在第一次通过dlopen()函数打开这个函数库,或者只是简单的作为共享函数库被打开的时候,_init函数被自动调用执行。与之相对应的就是_fini函数,当一个程序调用dlclose()去释放对这个函数库的引用的时候,如果该函数库的被引用计数器为0了,或者这个函数库是作为一般的共享函数库被使用而使用它的程序正常退出的时候,_fini就会被调用执行。C语言定义它们的原型如下:

void _init(void);

void _fini(void);

当用gcc编译源程序为“.o”文件的时候,需要加一个“-nostartfiles”选项。这个选项使得C编译器不链接系统的启动函数库里面的启动函数。否则,就会得到一个“multiple-definition”的错误。

5.3. 共享函数库也可以使脚本(Scripts)

GNU的loader允许使用特殊格式的脚本语言来写一个函数库。这对于那些需要间接包含其他函数库的情况还是有用的。例如,下面是一个/usr/lib/libc.so的例子:

/* GNU ld script Use the shared library, but some functions are only in

the static library, so try that secondarily. */

GROUP ( /lib/libc.so.6

/usr/lib/libc_nonshared.a )

更多的信息可以参考texinfo文档中关于ld链接的脚本部分。一般的信息还可以参考: info:ld#Options 和info:ld#Commands,也可以参考info:ld#Option Commands。

5.4. GNU libtool

如果你正在编译的系统想很方便的移植到其他操作系统下,你可以使用GNU libtool来创建和安装这个函数库。GNU libtool是一个函数库支持的典型的脚本。Libtool隐藏了使用一个可移植的函数库的负责性。Libtool提供了一个可以移植的界面来创建object文件,链接函数库(静态或者共享的),并且安装这些库。它还包含了libltdl,一个可移植的动态函数库调入程序的wrapper。更多的详细讨论,可以在https://www.doczj.com/doc/c39835034.html,/software/libtool/manual.html 看到。

5.5. 删除一些符号

在一个生产的文件中很多符号都是为了debug而包含的,占用了不少空间。如果空间不够,而且这些符号也许不再需要,就可以将其中一些删除。

最好的方法就是先正常的生成你需要的object文件,然后debug和测试你需要的一些东西。一旦你完全测试完毕了,就可以用strip去删除一些不需要的符号了。Strip命令可以使你很方便的控制删除什么符号,而保留什么符号。

Strip的具体用法可以参考其帮助文件。

另外的方法就是使用GNU ld的选项“-S”和“-s”;“-S”会删除一些debugger 的符号,而“-s”则是将所有的符号信息都删除。通常我们可以在gcc中加这样的参数“-Wl,-S”和“-Wl,-s”来达到这个目的。

6. 更多的例子

下面是一些例子,例子中我们会使用三种函数库(静态的、共享的和动态加载的函数库)。文件libhello.c是一个函数库,libhello.h 是它的头文件;demo_use.c则是一个使用了libhello函数库的。Script_static和script_dynamic分别演示如何以静态和共享方式使用函数库,而后面的demo_dynamic.c和script_dynamic则表示演示如何以动态加载函数库的方式来使用它。

6.1. File libhello.c

/* libhello.c - demonstrate library use. */

#include

void hello(void)

{

printf("Hello, library world.");

}

6.2. File libhello.h

/* libhello.h - demonstrate library use. */

void hello(void);

6.3. File demo_use.c

/* demo_use.c -- demonstrate direct use of the "hello" routine */ #include "libhello.h"

int main(void)

{

hello();

return 0;

}

6.4. File script_static

#!/bin/sh

# Static library demo

# Create static library's object file, libhello-static.o.

# I'm using the name libhello-static to clearly

# differentiate the static library from the

# dynamic library examples, but you don't need to use

# "-static" in the names of your

# object files or static libraries.

gcc -Wall -g -c -o libhello-static.o libhello.c

# Create static library.

ar rcs libhello-static.a libhello-static.o

# At this point we could just copy libhello-static.a

# somewhere else to use it.

# For demo purposes, we'll just keep the library

# in the current directory.

# Compile demo_use program file.

gcc -Wall -g -c demo_use.c -o demo_use.o

# Create demo_use program; -L. causes "." to be searched during # creation of the program. Note that this command causes

# the relevant object file in libhello-static.a to be

# incorporated into file demo_use_static.

gcc -g -o demo_use_static demo_use.o -L. -lhello-static

# Execute the program.

./demo_use_static

6.5. File script_shared

#!/bin/sh

# Shared library demo

# Create shared library's object file, libhello.o.

gcc -fPIC -Wall -g -c libhello.c

# Create shared library.

# Use -lc to link it against C library, since libhello

# depends on the C library.

gcc -g -shared -Wl,-soname,libhello.so.0 -o

libhello.so.0.0 libhello.o -lc

# At this point we could just copy libhello.so.0.0 into

# some directory, say /usr/local/lib.

# Now we need to call ldconfig to fix up the symbolic links.

# Set up the soname. We could just execute:

# ln -sf libhello.so.0.0 libhello.so.0

# but let's let ldconfig figure it out.

/sbin/ldconfig -n .

# Set up the linker name.

# In a more sophisticated setting, we'd need to make

# sure that if there was an existing linker name,

# and if so, check if it should stay or not.

ln -sf libhello.so.0 libhello.so

# Compile demo_use program file.

gcc -Wall -g -c demo_use.c -o demo_use.o

# Create program demo_use.

# The -L. causes "." to be searched during creation

# of the program; note that this does NOT mean that "."

# will be searched when the program is executed.

gcc -g -o demo_use demo_use.o -L. -lhello

# Execute the program. Note that we need to tell the program

# where the shared library is,

using LD_LIBRARY_PATH.LD_LIBRARY_PATH="."

./demo_use

6.6. File demo_dynamic.c

/* demo_dynamic.c -- demonstrate dynamic loading and

use of the "hello" routine */

/* Need dlfcn.h for the routines to dynamically load libraries */ #include

#include

#include

/* Note that we don't have to include "libhello.h".

However, we do need to specify something related;

we need to specify a type that will hold the value

we're going to get from dlsym(). */

/* The type "simple_demo_function" describes a function that takes no arguments, and returns no value: */

typedef void (*simple_demo_function)(void);

int main(void)

{

const char *error;

void *module;

simple_demo_function demo_function;

/* Load dynamically loaded library */

module = dlopen("libhello.so", RTLD_LAZY);

if (!module)

{

fprintf(stderr, "Couldn't open libhello.so: %s

",dlerror());

exit(1);

}

/* Get symbol */

dlerror();

demo_function = dlsym(module, "hello");

if ((error = dlerror()))

{

fprintf(stderr, "Couldn't find hello: %s

", error);

exit(1);

}

/* Now call the function in the DL library */

(*demo_function)();

/* All done, close things cleanly */

dlclose(module);

return 0;

}

6.7. File script_dynamic

#!/bin/sh

# Dynamically loaded library demo

# Presume that libhello.so and friends have

# been created (see dynamic example).

# Compile demo_dynamic program file into an object file. gcc -Wall -g -c demo_dynamic.c

# Create program demo_use.

# Note that we don't have to tell it where to search

C语言函数大全(m开头)

C语言函数大全(m开头) main()主函数 每一C 程序都必须有一 main() 函数, 可以根据自己的爱好把它放在程序的某 个地方。有些程序员把它放在最前面, 而另一些程序员把它放在最后面, 无论放 在哪个地方, 以下几点说明都是适合的。 1. main() 参数 在Turbo C2.0启动过程中, 传递main()函数三个参数: argc, argv和env。 * argc: 整数, 为传给main()的命令行参数个数。 * argv: 字符串数组。 在DOS 3.X 版本中, argv[0] 为程序运行的全路径名; 对DOS 3.0 以下的版本, argv[0]为空串("") 。 argv[1] 为在DOS命令行中执行程序名后的第一个字符串; argv[2] 为执行程序名后的第二个字符串; ... argv[argc]为NULL。 *env: 安符串数组。env[] 的每一个元素都包含ENVVAR=value形式的字符 串。其中ENVVAR为环境变量如PATH或87。value 为ENVVAR的对应值如C:\DOS, C: \TURBOC(对于PATH) 或YES(对于87)。 Turbo C2.0启动时总是把这三个参数传递给main()函数, 可以在用户程序中 说明(或不说明)它们, 如果说明了部分(或全部)参数, 它们就成为main()子程序 的局部变量。 请注意: 一旦想说明这些参数, 则必须按argc, argv, env 的顺序, 如以下 的例子: main() main(int argc) main(int argc, char *argv[]) main(int argc, char *argv[], char *env[])

C语言常用函数手册

1.分类函数,所在函数库为ctype.h int isalpha(int ch) 若ch是字母('A'-'Z','a'-'z')返回非0值,否则返回0 int isalnum(int ch) 若ch是字母('A'-'Z','a'-'z')或数字('0'-'9'),返回非0值,否则返回0 int isascii(int ch) 若ch是字符(ASCII码中的0-127)返回非0值,否则返回0 int iscntrl(int ch) 若ch是作废字符(0x7F)或普通控制字符(0x00-0x1F) 返回非0值,否则返回0 int isdigit(int ch) 若ch是数字('0'-'9')返回非0值,否则返回0 int isgraph(int ch) 若ch是可打印字符(不含空格)(0x21-0x7E)返回非0值,否则返回0 int islower(int ch) 若ch是小写字母('a'-'z')返回非0值,否则返回0 int isprint(int ch) 若ch是可打印字符(含空格)(0x20-0x7E)返回非0值,否则返回0 int ispunct(int ch) 若ch是标点字符(0x00-0x1F)返回非0值,否则返回0 int isspace(int ch) 若ch是空格(' '),水平制表符('\t'),回车符('\r'), 走纸换行('\f'),垂直制表符('\v'),换行符('\n') 返回非0值,否则返回0 int isupper(int ch) 若ch是大写字母('A'-'Z')返回非0值,否则返回0 int isxdigit(int ch) 若ch是16进制数('0'-'9','A'-'F','a'-'f')返回非0值, 否则返回0 int tolower(int ch) 若ch是大写字母('A'-'Z')返回相应的小写字母('a'-'z') int toupper(int ch) 若ch是小写字母('a'-'z')返回相应的大写字母('A'-'Z') 2.数学函数,所在函数库为math.h、stdlib.h、string.h、float.h int abs(int i) 返回整型参数i的绝对值 double cabs(struct complex znum) 返回复数znum的绝对值 double fabs(double x) 返回双精度参数x的绝对值 long labs(long n) 返回长整型参数n的绝对值 double exp(double x) 返回指数函数ex的值 double frexp(double value,int *eptr) 返回value=x*2n中x的值,n存贮在eptr中double ldexp(double value,int exp); 返回value*2exp的值 double log(double x) 返回logex的值 double log10(double x) 返回log10x的值 double pow(double x,double y) 返回xy的值 double pow10(int p) 返回10p的值 double sqrt(double x) 返回+√x的值 double acos(double x) 返回x的反余弦cos-1(x)值,x为弧度 double asin(double x) 返回x的反正弦sin-1(x)值,x为弧度 double atan(double x) 返回x的反正切tan-1(x)值,x为弧度 double atan2(double y,double x) 返回y/x的反正切tan-1(x)值,y的x为弧度double cos(double x) 返回x的余弦cos(x)值,x为弧度 double sin(double x) 返回x的正弦sin(x)值,x为弧度 double tan(double x) 返回x的正切tan(x)值,x为弧度 double cosh(double x) 返回x的双曲余弦cosh(x)值,x为弧度 double sinh(double x) 返回x的双曲正弦sinh(x)值,x为弧度

C语言标准库函数2012

常用C语言标准库函数2012 C语言编译系统提供了众多的预定义库函数和宏。用户在编写程序时,可以直接调用这些库函数和宏。这里选择了初学者常用的一些库函数,简单介绍了各函数的用法和所在的头文件。 1.测试函数 Isalnum 原型:int isalnum(int c) 功能:测试参数c是否为字母或数字:是则返回非零;否则返回零 头文件:ctype.h Isapha 原型:int isapha(int c) 功能:测试参数c是否为字母:是则返回非零;否则返回零 头文件:ctype.h Isascii 原型:int isascii(int c) 功能:测试参数c是否为ASCII码(0x00~0x7F):是则返回非零;否则返回零 头文件:ctype.h Iscntrl 原型:int iscntrl(int c) 功能:测试参数c是否为控制字符(0x00~0x1F、0x7F):是则返回非零;否则返回零 头文件:ctype.h Isdigit 原型:int isdigit(int c) 功能:测试参数c是否为数字:是则返回非零;否则返回零。 头文件:ctype.h Isgraph 原型:int isgraph(int c) 功能:测试参数c是否为可打印字符(0x21~0x7E):是则返回非零;否则返回零头文件:ctype.h Islower 原型:int islower(int c) 功能:测试参数c是否为小写字母:是则返回非零;否则返回零 头文件:ctype.h

Isprint 原型:int isprint(int c) 功能:测试参数c是否为可打印字符(含空格符0x20~0x7E):是则返回非零;否则返回零 头文件:ctype.h Ispunct 原型:int ispunct(int c) 功能:测试参数c是否为标点符号:是则返回非零;否则返回零 头文件:ctype.h Isupper 原型:int isupper(inr c) 功能:测试参数c是否为大写字母:是则返回非零;否则返回零 Isxdigit 原型:int isxdigit(int c) 功能:测试参数c是否为十六进制数:是则返回非零;否则返回零 2.数学函数 abs 原型:int abs(int i) 功能:返回整数型参数i的绝对值 头文件:stdlib.h,math.h acos 原型:double acos(double x) 功能:返回双精度参数x的反余弦三角函数值 头文件:math.h asin 原型:double asin(double x) 功能:返回双精度参数x的反正弦三角函数值 头文件:math.h atan 原型:double atan(double x) 功能:返回双精度参数的反正切三角函数值 头文件:math.h atan2 原型:double atan2(double y,double x) 功能:返回双精度参数y和x由式y/x所计算的反正切三角函数值 头文件:math.h cabs

C语言函数库详解(收藏版)

c语言函数库 目录 第一章(C标准库) (4) 1. :诊断 (4) 2. :字符类别测试 (5) 3. :错误处理 (5) 4. :整型常量 (6) 5. :地域环境 (6) 6. :数学函数 (7) 7. :非局部跳转 (8) 8. :信号 (9) 9. :可变参数表 (11) 10. :公共定义 (11) 11. :输入输出 (12) 12. :实用函数 (13) 13. :日期与时间函数 (13) 第二章(IO函数) (14) clearerr:复位错误标志函数 (15) feof:检测文件结束符函数 (16) ferror:检测流上的错误函数 (17) fflush:清除文件缓冲区函数 (18) fgetc:从流中读取字符函数 (19) fgetpos:取得当前文件的句柄函数 (20) fgets:从流中读取字符串函数 (21) fopen、fclose:文件的打开与关闭函数 (22) fprintf:格式化输出函数 (23) fputc:向流中输出字符函数 (25) fputs:向流中输出字符串函数 (25) fread:从流中读取字符串函数 (26) freopen:替换文件中数据流函数 (27) fscanf:格式化输入函数 (28) fseek:文件指针定位函数 (28) fsetpos:定位流上的文件指针函数 (30) ftell:返回当前文件指针位置函数 (31) fwrite:向文件写入数据函数 (31) getc:从流中读取字符函数 (32) getchar:从标准输入文件中读取字符函数 (33) gets:从标准输入文件中读取字符串函数 (34) perror:打印系统错误信息函数 (34) printf:产生格式化输出的函数 (35) putc:向指定流中输出字符函数 (36) putchar:向标准输出文件上输出字符 (37)

C语言函数大全

C语言函数大全 1 字符测试函数 函数(及意义)函数分解Isalnum(){判断字符是否is alphbet(字母表) number(数字) 为字母或数字} Isalpha(){判断是否为英文is alphbet(字母表) 字母} Isblank(){空格和TAB} is blank(空格) Iscntrl() { 控制} is control(控制) Isdigit(){数字} is digit(数字) Isgraph(){除空格外的可打is graph(图表) 印字符} Islower(){是否为小写} is lowercase(小写) Isprintf(){可打印字符含空这个简单 字符} Ispunct(){标点或特殊符号is punctuation(标点) } Isspace(){检查是否为空字is space(空间) 符,即判断是否为空格,水平 定位字符“\t”,归位字符“\r ”,垂直定位字符“\v”,换行 字符“\n”,翻页“\f”} Isupper(){是否为大写字母is upper_case(大写) } Isxdigit(){十六进制} is hexadecimal digit(十六进制) Tolower(){将小写转换成 大写} Toupper(){将大写转换成这个简单(to change 或者to covert 或者 小写} transformation

字符串函数 Memchr(){在某一内存范围内查找一特定字符}Memory (储存)char(字符型炭)也可以是character (字符) Memcmp(){比较区域 str1,str2的前n个字节} Memory(同理)compare(比较) Memcpy(){由str2所指内存区域复 制n个字节到str1所指内存区域} Memory copy(复制) Memmove(){两个所指的内存区域 可重叠,但是内容会更改,函数 返回值为指向区域内存的指针} Memory move(移动) Memset(){把str所指的内存区域 的前N个字节设置成字符c} Set(设置)

C语言中常用的库函数

字符处理函数 本类别函数用于对单个字符进行处理,包括字符的类别测试和字符的大小写转换 头文件ctype.h 函数列表<> 函数类别函数用途详细说明 字符测试是否字母和数字isalnum 是否字母isalpha 是否控制字符iscntrl 是否数字isdigit 是否可显示字符(除空格外)isgraph 是否可显示字符(包括空格)isprint 是否既不是空格,又不是字母和数字的可显示字符ispunct 是否空格isspace 是否大写字母isupper 是否16进制数字(0-9,A-F)字符isxdigit 字符大小写转换函数转换为大写字母toupper 转换为小写字母tolower 地区化 本类别的函数用于处理不同国家的语言差异。 头文件local.h 函数列表 函数类别函数用途详细说明 地区控制地区设置setlocale 数字格式约定查询国家的货币、日期、时间等的格式转换localeconv 数学函数 本分类给出了各种数学计算函数,必须提醒的是ANSI C标准中的数据格式并不符合IEEE754标准,一些C语言编译器却遵循IEEE754(例如frinklin C51) 头文件math.h 函数列表 函数类别函数用途详细说明 错误条件处理定义域错误(函数的输入参数值不在规定的范围内) 值域错误(函数的返回值不在规定的范围内) 三角函数反余弦acos 反正弦asin

反正切atan 反正切2 atan2 余弦cos 正弦sin 正切tan 双曲函数双曲余弦cosh 双曲正弦sinh 双曲正切tanh 指数和对数指数函数exp 指数分解函数frexp 乘积指数函数fdexp 自然对数log 以10为底的对数log10 浮点数分解函数modf 幂函数幂函数pow 平方根函数sqrt 整数截断,绝对值和求余数函数求下限接近整数ceil 绝对值fabs 求上限接近整数floor 求余数fmod 本分类函数用于实现在不同底函数之间直接跳转代码。头文件setjmp.h io.h 函数列表 函数类别函数用途详细说明 保存调用环境setjmp 恢复调用环境longjmp 信号处理 该分类函数用于处理那些在程序执行过程中发生例外的情况。 头文件signal.h 函数列表 函数类别函数用途详细说明 指定信号处理函数signal 发送信号raise 可变参数处理 本类函数用于实现诸如printf,scanf等参数数量可变底函数。

C语言常用的库函数

库函数并不是C语言的一部分,它是由编译系统根据一般用户的需要编制并 提供给用户使用的一组程序。每一种C编译系统都提供了一批库函数,不同的 编译系统所提供的库函数的数目和函数名以及函数功能是不完全相同的。ANSI C标准提出了一批建议提供的标准库函数。它包括了目前多数C编译系统所提供 的库函数,但也有一些是某些C编译系统未曾实现的。考虑到通用性,本附录 列出ANSI C建议的常用库函数。 由于C库函数的种类和数目很多,例如还有屏幕和图形函数、时间日期函数、 与系统有关的函数等,每一类函数又包括各种功能的函数,限于篇幅,本附录不 能全部介绍,只从教学需要的角度列出最基本的。读者在编写C程序时可根据 需要,查阅有关系统的函数使用手册。 1.数学函数 使用数学函数时,应该在源文件中使用预编译命令: #include或#include "math.h" 函数名函数原型功能返回值 acos double acos(double x);计算arccos x的值,其中-1<=x<=1计算结果 asin double asin(double x);计算arcsin x的值,其中-1<=x<=1计算结果 atan double atan(double x);计算arctan x的值计算结果 atan2double atan2(double x, double y);计算arctan x/y的值计算结果 cos double cos(double x);计算cos x的值,其中x的单位为弧度计算结果 cosh double cosh(double x);计算x的双曲余弦cosh x的值计算结果 exp double exp(double x);求e x的值计算结果

C语言常见基本词汇及词汇解释

C语言常用基本词汇及其他提示语运算符与表达式: 1.constant 常量 2. variable 变量 3. identify 标识符 4. keywords 关键字 5. sign 符号 6. operator 运算符 7. statement语句 8. syntax 语法 9. expression 表达式 10. initialition初始化 11. number format 数据格式 12 declaration 说明 13. type conversion 类型转换 14.define 、definition 定义 条件语句: 1.select 选择 2. expression 表达式 3. logical expression 逻辑表达式 4. Relational expression 关系表达式 5.priority优先

6. operation运算 7.structure 结构 循环语句: 1.circle 循环 2. condition 条件 3. variant 变量 4. process过程 5.priority优先 6. operation运算 数组: 1. array 数组 2. reference 引用 3. element 元素 4. address 地址 5. sort 排序 6. character 字符 7. string 字符串 8. application 应用函数: 1.call 调用 2.return value 返回值 3.function 函数

4. declare 声明 5. `parameter 参数 6.static 静态的 7.extern 外部的 指针: 1. pointer 指针 2. argument 参数 3. array 数组 4. declaration 声明 5. represent 表示 6. manipulate 处理 结构体、共用体、链表: 1 structure 结构 2 member成员 3 tag 标记 4 function 函数 5 enumerate 枚举 6 union 联合(共用体) 7 create 创建 8 insert 插入 9 delete 删除 10 modify 修改

C语言函数大全

功能: 异常终止一个进程 用法: void abort(void) 函数名: abs 功能: 求整数的绝对值 用法: int abs(int i) 函数名: absread, abswirte 功能: 绝对磁盘扇区读、写数据 用法: int absread(int drive, int nsects, int sectno, void *buffer) int abswrite(int drive, int nsects, in tsectno, void *buffer 函数名: access 功能: 确定文件的访问权限 用法: int access(const char *filename, int amode) 函数名: acos 功能:反余弦函数 用法: double acos(double x) 函数名: allocmem 功能: 分配DOS存储段 用法:int allocmem(unsigned size, unsigned *seg) 函数名: arc 功能: 画一弧线 用法:void far arc(int x, int y, int stangle, int endangle, int radius)函数名: asctime 功能: 转换日期和时间为ASCII码 用法:char *asctime(const struct tm *tblock) 函数名: asin 功能:反正弦函数 用法: double asin(double x) 函数名: assert 功能: 测试一个条件并可能使程序终止 用法:void assert(int test) 函数名: atan 功能: 反正切函数 用法: double atan(double x)

C语言文件操作函数大全(超详细)

fopen(打开文件) 相关函数 open,fclose 表头文件 #include 定义函数 FILE * fopen(const char * path,const char * mode); 函数说明参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。 mode有下列几种形态字符串: r 打开只读文件,该文件必须存在。 r+ 打开可读写的文件,该文件必须存在。 w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。 w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。 a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。 a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 复制代码代码如下: r Open text file for reading. The stream is positioned at the begin ning of the file. r+ Open for reading and writing. The stream is positioned at the begi nning of the file. w Truncate file to zero length or create text file for writing. The stream is positioned at the beginning of the file.

c语言中常用的函数和头文件

头文件ctype.h 函数列表<> 函数类别函数用途详细说明 字符测试是否字母和数字isalnum 是否字母isalpha 是否控制字符iscntrl 是否数字isdigit 是否可显示字符(除空格外)isgraph 是否可显示字符(包括空格)isprint 是否既不是空格,又不是字母和数字的可显示字符ispunct 是否空格isspace 是否大写字母isupper 是否16进制数字(0-9,A-F)字符isxdigit 字符大小写转换函数转换为大写字母toupper 转换为小写字母tolower 地区化 本类别的函数用于处理不同国家的语言差异。 头文件local.h 函数列表 函数类别函数用途详细说明 地区控制地区设置setlocale 数字格式约定查询国家的货币、日期、时间等的格式转换localeconv 数学函数 本分类给出了各种数学计算函数,必须提醒的是ANSI C标准中的数据格式并不符合IEEE754标准,一些C语言编译器却遵循IEEE754(例如frinklin C51) 头文件math.h 函数列表 函数类别函数用途详细说明 错误条件处理定义域错误(函数的输入参数值不在规定的范围内) 值域错误(函数的返回值不在规定的范围内) 三角函数反余弦acos 反正弦asin 反正切atan 反正切2 atan2 余弦cos

正弦sin 正切tan 双曲函数双曲余弦cosh 双曲正弦sinh 双曲正切tanh 指数和对数指数函数exp 指数分解函数frexp 乘积指数函数fdexp 自然对数log 以10为底的对数log10 浮点数分解函数modf 幂函数幂函数pow 平方根函数sqrt 整数截断,绝对值和求余数函数求下限接近整数ceil 绝对值fabs 求上限接近整数floor 求余数fmod 本分类函数用于实现在不同底函数之间直接跳转代码。头文件setjmp.h io.h 函数列表 函数类别函数用途详细说明 保存调用环境setjmp 恢复调用环境longjmp 信号处理 该分类函数用于处理那些在程序执行过程中发生例外的情况。 头文件signal.h 函数列表 函数类别函数用途详细说明 指定信号处理函数signal 发送信号raise 可变参数处理 本类函数用于实现诸如printf,scanf等参数数量可变底函数。 头文件stdarg.h 函数列表

C语言中最常用标准库函数 - candyliuxj - CSDN博客

C语言中最常用标准库函数- candyliuxj - CSDN博客 C语言中最常用标准库函数收藏 标准头文件包括: <asset.h> <ctype.h> <errno.h> <float.h> <limits.h> <locale.h> <math.h> <setjmp.h> <signal.h> <stdarg.h> <stddef.h> <stdlib.h> <stdio.h> <string.h> <time.h> 一、标准定义(<stddef.h>) 文件<stddef.h>里包含了标准库的一些常用定义,无论我们包含哪个标准头文件,<stddef.h>都会被自动包含进来。 这个文件里定义: l 类型size_t (sizeof运算符的结果类型,是某个无符号整型); l 类型ptrdiff_t(两个指针相减运算的结果类型,是某个有符号整型);

l 类型wchar_t (宽字符类型,是一个整型,其中足以存放本系统所支持的所有本地环境中的 字符集的所有编码值。这里还保证空字符的编码值为0); l 符号常量NULL (空指针值); l 宏offsetor (这是一个带参数的宏,第一个参数应是一个结构类型,第二个参数应是结构 成员名。offsetor(s,m)求出成员m在结构类型t的变量里的偏移量)。 注:其中有些定义也出现在其他头文件里(如NULL)。 二、错误信息(<errno.h>) <errno.h>定义了一个int类型的表达式errno,可以看作一个变量,其初始值为0,一些标准库函数执行中出错时将它设为非0值,但任何标准库函数都设置它为0。 <errno.h>里还定义了两个宏EDOM和ERANGE,都是非0的整数值。数学函数执行中遇到参数错误,就会将errno 置为EDOM,如出现值域错误就会将errno置为ERANGE。 三、输入输出函数(<stdio.h>) 文件打开和关闭: FILE *fopen(const char *filename, const char *mode); int fclose(FILE * stream);

C语言中常见的功能函数

C语言中常见的功能函数(应掌握的编程) 1、两个变量值的交换 void exchang(float *x,float *y) /*形参为两个变量的地铁(指针)*/ {float z; z=*x; *x=*y; *y=z; } void main() {float a,b; scanf(“%f%f”,&a,&b); exchang(&a,&b); /*因为形参是指针,所以实参必须给变量的地址,不能给变量名*/ printf(“a=%f,b=%f”,a,b); } 2、判断一个整数的奇偶 int jou(int n) /*如果是奇数返回1,否则返回0*/ { if(n%2==0) return 0; return 1; } 3、小写字符转换成大写字符 根据实参传给形参的字母,判断是否是小写字母,如果是小写字母,则转换成大写字母,否则不进行转换,函数返回转换后或原来的字符。 本函数仿照toupper()库函数的功能编写(toupper(c) 是将变量c字母转换成大写字母,如果不是小写字母不转换)。 char toupper1(char ch) {if(ch>=’a’&&ch<=’z’) ch-=32; /*小写字母比对应的大写字母ASCII码值大32*/ return ch; } 4、判断一个字符是否是字母(或数字) 根据实参传给形参的字符,判断是否是字母(或数字),如果是字母(或数字)返回1,否则返回0。此函数是根据库函数isalpha()(或isdigit())来编写的。 int isalpha1(char ch) /*判断是否是字母*/ {if(ch>=’A’&&ch<=’Z’||ch>=’a’&&ch<=’z’) return 1; else return 0; } int isdigit1(char ch) /*判断是否是数字字符*/ {if(ch>=’0’&&ch<=’9’) return 1; else return 0; } 5、根据学生成绩,返回其等级 char fun(float cj) {char c; switch((int)cj/10) {case 10:

C语言库函数

分类函数,所在函数库为ctype.h int isalpha(int ch) 若ch是字母('A'-'Z','a'-'z')返回非0值,否则返回0 int isalnum(int ch) 若ch是字母('A'-'Z','a'-'z')或数字('0'-'9') 返回非0值,否则返回0 int isascii(int ch) 若ch是字符(ASCII码中的0-127)返回非0值,否则返回0 int iscntrl(int ch) 若ch是作废字符(0x7F)或普通控制字符(0x00-0x1F) 返回非0值,否则返回0 int isdigit(int ch) 若ch是数字('0'-'9')返回非0值,否则返回0 int isgraph(int ch) 若ch是可打印字符(不含空格)(0x21-0x7E)返回非0值,否则返回0 int islower(int ch) 若ch是小写字母('a'-'z')返回非0值,否则返回0 int isprint(int ch) 若ch是可打印字符(含空格)(0x20-0x7E)返回非0值,否则返回0 int ispunct(int ch) 若ch是标点字符(0x00-0x1F)返回非0值,否则返回0 int isspace(int ch) 若ch是空格(' '),水平制表符('\t'),回车符('\r'), 走纸换行('\f'),垂直制表符('\v'),换行符('\n') 返回非0值,否则返回0 int isupper(int ch) 若ch是大写字母('A'-'Z')返回非0值,否则返回0 int isxdigit(int ch) 若ch是16进制数('0'-'9','A'-'F','a'-'f')返回非0值, 否则返回0 int tolower(int ch) 若ch是大写字母('A'-'Z')返回相应的小写字母('a'-'z') int toupper(int ch) 若ch是小写字母('a'-'z')返回相应的大写字母('A'-'Z') 数学函数,所在函数库为math.h、stdlib.h、string.h、float.h int abs(int i) 返回整型参数i的绝对值 double cabs(struct complex znum) 返回复数znum的绝对值 double fabs(double x) 返回双精度参数x的绝对值 long labs(long n) 返回长整型参数n的绝对值 double exp(double x) 返回指数函数ex的值 double frexp(double value,int *eptr) 返回value=x*2n中x的值,n存贮在eptr中

c语言库函数大全

Afx全局函数 AfxBeginThread:开始一个新的线程 AfxEndThread:结束一个旧的线程 AfxFormatString1:类似printf一般地将字符串格式化 AfxFormatString2:类似printf一般地将字符串格式化 AfxMessageBox:类似Windows API 函数MessageBox AfxOuputDebugString:将字符串输往除错装置 AfxGetApp:获得application object (CWinApp派生对象)的指针 AfxGetMainWnd:获得程序主窗口的指针 AfxGetInstance:获得程序的instance handle MFC数据类型 下面这些是和Win32程序共同使用的数据类型 BOOL:布尔值,取值为TRUE or FALSE BSTR:32-bit 字符指针 BYTE:8-bit整数,未带正负号 COLORREF:32-bit数值,代表一个颜色值 DWORD:32-bit整数,未带正负号 LONG:32-bit整数,带正负号 LPARAM:32-bit整数,作为窗口函数或callback函数的一个参数 LPCSTR:32-bit指针,指向一个常数字符串 LPSTR:32-bit指针,指向一个字符串 LPCTSTR:32-bit指针,指向一个常数字符串,此字符串可以移植到Unicode(世界性的字符集)和DBCS(亚洲字符集) LPTSTR:32-bit指针,指向一个字符串,此字符串可以移植到Unicode和DBCS LPVOID:32-bit指针,指向一个未指定类型的数据 LPRESULT:32-bit数值,作为窗口函数或callback函数的返回值 UINT:在Win16中是一个16-bit 未带正负号整数,在Win32中是一个32-bit 未带正负号整数,WNDPROC:32-bit指针,指向一个窗口函数 WORD:16-bit 整数,未带正负号 WPARAM:窗口函数或callback函数的一个参数,在Win16中是16-bit,在Win32中是32-bit 下面这些是MFC独特的数据类型 POSITION:一个数值,代表collection对象(例如数组或链表)中的元素位置,常用于MFC collection classes (即数据处理类,如CArray) LPCRECT:32-bit指针,指向一个不变的RECT结构 CSize说明一个矩形的高和宽,调用CDC::GetTextExtent成员函数计算使用当前字体的一行文字的高和宽决定的尺寸。 CString::LoadString把一个由nID标识的字符串资源读取到现有的CString对象中 CDC::BeginPath:打开设备上下文中的路径,路径打开后,应用程序可以开始调用GDI画图函数定义位于路径上的点。 CDC::SelectClipPath选择当前路径作为设备上下文的剪切区域,通过使用指定模式与任何现有的剪切区域

常用C语言标准库函数

常用C语言标准库函数 C语言编译系统提供了众多的预定义库函数和宏。用户在编写程序时,可以直接调用这些库函数和宏。这里选择了初学者常用的一些库函数,简单介绍了各函数的用法和所在的头文件。 1.测试函数 Isalnum 原型:int isalnum(int c) 功能:测试参数c是否为字母或数字:是则返回非零;否则返回零 头文件:ctype.h Isapha 原型:int isapha(int c) 功能:测试参数c是否为字母:是则返回非零;否则返回零 头文件:ctype.h Isascii 原型:int isascii(int c) 功能:测试参数c是否为ASCII码(0x00~0x7F):是则返回非零;否则返回零 头文件:ctype.h Iscntrl 原型:int iscntrl(int c) 功能:测试参数c是否为控制字符(0x00~0x1F、0x7F):是则返回非零;否则返回零头文件:ctype.h Isdigit 原型:int isdigit(int c) 功能:测试参数c是否为数字:是则返回非零;否则返回零。 头文件:ctype.h Isgraph 原型:int isgraph(int c) 功能:测试参数c是否为可打印字符(0x21~0x7E):是则返回非零;否则返回零 头文件:ctype.h Islower 原型:int islower(int c) 功能:测试参数c是否为小写字母:是则返回非零;否则返回零 头文件:ctype.h Isprint 原型:int isprint(int c) 功能:测试参数c是否为可打印字符(含空格符0x20~0x7E):是则返回非零;否则返回零 头文件:ctype.h Ispunct 原型:int ispunct(int c) 功能:测试参数c是否为标点符号:是则返回非零;否则返回零

C语言中的22个数学函数

C语言的22个数学函数 在使用C语言数学函数时候,应该在该源文件中使用以下命令行: #include <> 或#include "",这里的<>跟""分别表示:前者表示系统到存放C库函数头文件所在的目录寻找需要包含的文件,这是标准方式;后者表示系统先在拥护当前目录中寻找要包含的文件,若找不到,再按前者方式查找。为节省时间,在使用自己编写的文件时使用的是“”,自己编写的文件一般是在当前目录下。 22个数学函数中只有abs的数据类型是:”整型“,”int“。 log10、logE中的10与E是在log的左下角位置。其余求弧度函数需要看清楚是不是指数。 排列方式如下:函数名:函数功能参数介绍,返回值,说明。函数原型。 abs: 求整型x的绝对值,返回计算结果。 int abs(int x); acos:计算COS-1(x)的值,返回计算结果,x应在-1到1范围内。 double acos(double x); asin: 计算SIN-1(x)的值,返回计算结果,x应在-1到1范围内。 double asin(double x); atan: 计算TAN-1(x)的值,返回计算结果。double atan(double x); atan2: 计算TAN-1/(x/y)的值,返回计算结果。 double atan2(double x,double y); cos: 计算COS(x)的值,返回计算结果,x的单位为弧度。 double cos(double x); cosh: 计算x的双曲余弦COSH(x)的值,返回计算结果。 double cosh(double x); exp: 求e x的值,返回计算结果。 double exp(double x); fabs: 求x的绝对值,返回计算结果。 duoble fabs(fouble x); floor: 求出不大于x的最大整数,返回该整数的双精度实数。 double floor(double x); fmod: 求整除x/y的余数,返回该余数的双精度。 double fmod(double x,double y); frexp: 把双精度数val分解为数字部分(尾数)x和以2为底的指数n,即val=x*2n,n存放在eptr 指向的变量中。返回数字部分<=x<1。 double frexp(double x, double *eptr); log: 求log e x,ln x。返回计算结果。 double log(double x); log10: 求log10x。返回计算结果。 double log10(double x); modf: 把双精度数val分解为整数部分和小数部分,把整数部分存到iptr指向的单元。返回val 的小数部分。 double modf(double val,double *iptr); pow: 计算x y的值,返回计算结果。 double pow(double x,double y); rand: 产生-90到32767间的随机整数。返回随机整数。 int rand(void); sin: 计算SINx的值。返回计算结果。x单位为弧度。 double sin(double x); sinh: 计算x的双曲正弦函数SINH(x)的值,返回计算结果。 double sinh(double x); sqrt: 计算根号x。返回计算结果。x应>=0。 double sqrt(double x); tan: 计算TAN(x)的值,返回计算结果。x单位为弧度。 double tan(double x); tanh: 计算x的双曲正切函数tanh(x)的值。返回计算结果。 double tanh(double x);

C语言函数大全六.docx

gcvt 功能 把双精度数转化成字符串的函数 头文件 stdlib.h 语法 char*gcvt(value, ndigit,buf) getc 功能 从流屮取字符的宏 头文件 stdio.h 语法 int getc(FILE *stream) getchar 功能 从stdin流中读取一个字符的函数 头文件 39 错误!超链接引用无效。从入门到精通 stdio.h

字符型变最=getchar getcurdir 功能 读収指定驱动器的当前目录的函数 头文件 dir.h 语法 int getcurdir(int drive,char directory) drive=0(缺省);1 (A 驱动器);... directory用来存放目录名,不包括驱动器名,不以反斜杠开始。 返冋值 0(删IJ成功);1(出错)getcwd 功能 读取当前冃录的函数 头文件 dir.h 语法 char *getcwd(char *buf,int buflen) 返回值 若buf非空,调用成功返回buf,出错返回NULL;若buf为NULL,返回指向己经分配的内存缓冲区地址。

getdate 功能 读取系统日期函数 头文件 dos.h 语法 void getdate(pdate)struct date{int da_year;int da_day;int da_mon;}; struct date *pdate; getdfree 功能 读取磁盘空闲空间的函数 头文件 dir.h 语法 void getdfree(drive,dtable) getdisk 功能 读取当前磁盘驱动器号函数

相关主题
文本预览
相关文档 最新文档