分类 编程语言 下的文章

一、静态库和动态库

静态库是指程序在编译阶段就把库文件嵌入到程序中的三方库,这种行为在程序运行前就已经决定了,程序在编译完成后不再依赖库文件。

动态库和静态库不一样,它是在程序运行期间才发生的调用行为,不会嵌入到程序,相对来说,链接动态库的二进制文件体积更小。

windows和linux平台下的静态/动态库后缀分别为lib dll.a .so,其中linux中动态库的命名规则为:libxxx.so.x.y.z,xxx表示库名,x是主版本号,y是此版本号,z是发行版本号。

- 阅读剩余部分 -

  • -l:表明需要一起编译的库文件。
  • -L:添加库文件所在的目录,只针对静态库。
  • -c:生成目标文件*.o
  • -o:指定输出文件。

静态库的使用方法

库文件名字为libxxx.a或者libxxx.so,使用时通过-l链接:

gcc -lxxx main.c

如果库文件不在/lib, /usr/lib/usr/local/lib三者中的任一个文件夹的话,要通过-L选项指定库所在的目录,否则会报错:/usr/bin/ld: cannot find -lxxx

> make
gcc main.c -lfunc1 -o debug/app # 没有制定库所在路径报错
/usr/bin/ld: cannot find -lfunc1
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target ''app'' failed
make: *** [app] Error 1
> vi Makefile # 修改Makefile添加-L选项
> make
gcc main.c -L. -lfunc1 -o debug/app # 编译成功

一、Makefile概述

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。Makefile的基本语法规则为:

目标: 依赖
    操作

例如我们要把一个main.c编译成app,这里目标是app,源是main.c,编译的命令为gcc main.c -o app。那么它的Makefile为:

app: main.c
    gcc main.c -o app

- 阅读剩余部分 -

fgets函数的声明如下:

char *fgets(char *s, int size, FILE *stream);

s表示待接收字符串的缓冲区,size为最大大小,stream为读取的数据流。

对于数据的读取来说,函数实际最多读到size - 1个字节,如果读取的数据比这个长,会自动截断,保证在最后以\0结尾,要注意的是读取字符时会把\n也读进来

- 阅读剩余部分 -

一、可变长参数介绍

某些情况下为了完成一些功能,需要用到可变长参数的函数,例如我们最常用的printf和scanf函数:

scanf("%d %d", &a, &b);
printf("%d %d\n", a, b);

它们首先都是一个字符串打头,后面再跟上不定数量的参数,为我们的输出形式提供了多样性。

对于像这样的不定长参数的函数来说,它的声明形式为:

int func(int a, int b, ...);

- 阅读剩余部分 -

判断编译器是C或者C++

通过__cplusplus判断C/C++:

// 如果是C++,使用扩展C的关键字
#ifdef __cplusplus
extern "C" {
#endif

struct string_t *create_string(int max_len);
struct string_t *copy_string(const char *str);
void release_string(struct string_t *str);

#ifdef __cplusplus
}
#endif

- 阅读剩余部分 -

一、luaL_dofile(): cannot open ./lib.lua: No such file or directory

问题原因

运行应用的目录和lua文件不在同一个目录,.lua文件所在的目录是当前所在的目录而不是程序所在目录。

ma@ubuntu:/data/code/lua/2-lua和c++/cpp-lua$ tree
.
├── debug
│   └── app
├── lib.lua
├── main.cpp
└── Makefile

1 directory, 6 files

app在当前目录下的debug目录下,在当前目录下执行./debug/app可以成功读取到lib.lua,但是在debug目录下执行./app就会报错。

- 阅读剩余部分 -

一、父子进程共享内容

相同处

全局变量,.data, .text、堆栈,环境变量,用户id工作目录。

重点:文件描述符,mmap建立的映射区。

不同处

进程ID、fork返回值、各自父进程、进程运行时间、定时器,未决信号集。

子进程复制了父进程的用户空间,遵循读时共享,写时复制原则。

- 阅读剩余部分 -

reserve方法用来给vector预留空间,预留的空间只会改变capacity的大小,不会改变size大小。resize方法表示重新调整数组大小,capacity和size都会改变。

使用reserve后,不能直接使用下标来增加元素,虽然内存是已经分配了直接使用不会报错,但是直接通过下标来复制会导致其他参数得不到更新(如size),会导致意想不到的错误。如以下代码:

int i;
vector<int> v;
v.reserve(10);
cout << "cap: " << v.capacity() << ", size: " << v.size() << endl;
for (i = 0; i < 10; i++) {
    v[i] = i;
}
cout << "cap: " << v.capacity() << ", size: " << v.size() << endl;

输出:

cap: 10, size: 0
cap: 10, size: 0

通过下标给数组中的每个元素复制,实际上本身数组的长度并没有得到增长,一旦再执行push_back就会导致前面的数据被覆盖。正确的方式是使用push_back或者insert方法插入元素。