undefined

一、宏

1. 为什么要有宏

因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。

而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率

2. 宏的问题

缺点:

  • 宏没有类型检测,不安全
查看更多

undefined

一、仿函数

Functor/Function Object翻译过来就是仿函数,它是通过重载()运算符模拟函数行为的类。也就是说,它不是函数(所以仿函数翻译的很贴切)。因为它重载了()运算符,因此可以像调用函数一样对它进行调用。STL中大量运用了Function Object,也提供了很多预先定义的Function Object。还是从vector遍历举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PrintInt
{
public:
void operator()(int elem) const
{
std::cout<<elem<<' ';
}
};

std::vector<int> v;
for_each(v.begin(),v.end(), PrintInt());

//C++ 11 lambda stype
for_each(begin(v), end(v), [](int n){ cout<< n <<", "; });

仿函数的优点:

1.仿函数是对象,可以拥有成员函数和成员变量,即仿函数拥有状态(states)
2.每个仿函数都有自己的类型
3.仿函数通常比一般函数快(很多信息编译期确定)

查看更多

undefined

1. podfile 指定第三方 SDK 的版本

podfile语法参考: https://www.cnblogs.com/lxlx1798/p/14587268.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
source 'https://github.com/Artsy/Specs.git'  # 指明依赖库的来源地址


target 'Test' do
platform:ios,'10.0' # 指明平台是 ios,版本是 10.0
pod 'AFNetworking', '~> 2.6.3'
pod 'test', '1.0' # 指定版本号为 1.0
pod 'test', :git => 'https://github.com/xxx/test.git' # 引入 master 分支(默认)
pod 'test', :git => 'https://github.com/xxx/test.git', :branch => 'dev' # 引入指定的分支
pod 'test', :git => 'https://github.com/xx/test.git', :tag => '0.0.1' # 引入某个 tag 的代码
pod 'test', :git => 'https://github.com/xxx/test.git', :commit => '02149723' # 引入某个特殊的提交节点
pod 'test', :podspec => 'https://example.com/JSONKit.podspec' # podspec 可以从另一个源库的地址引入
pod 'test', :path => '~/Desktop/BIZUtils/trunk/' # 指定 pod 地址为本地
end

2. 第三方库的操作

1
2
3
4
5
6
7
8
9
10
11
1. 更新指定的第三方库
pod update 库名

2. 把 podfile 内全部的库更新,重新安装
pid install

3. 只安装新添加的库,已更新的库忽略
pod install --verbose --no-repo-update

4. 只更新指定的库,其他库忽略
pod update 库名 --verbose --no-repo-update

查看更多

undefined

C 语言中 errno 及其相关用法

errno 在 <errno.h> 头文件中定义。如下:

1
2
3
#ifndef errno
extern int errno;
#endif

在 linux 中使用 c 语言编程,errno 可以把最后一次调用系统调用的错误代码保留。errno 是在调用库函数之前先清零,然后再进行检查。

1. strerror 使用

strerror 返回一个错误消息字符串的指针。

查看更多

undefined

读取目录下所有文件(包括子目录)

Linux C 下读取目录要用到结构体 struct dirent。在头文件 #include <dirent.h>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct dirent {
__ino64_t d_ino; // inode number 索引节点号
__off64_t d_off; // offset to this dirent 在目录文件中的偏移
unsigned short int d_reclen; // length of this d_name 文件名长度
unsigned char d_type; // the type of d_name 文件类型
char d_name[256]; /* We must not include limits.h! 文件名,最长 255 字符 */
};

enum {
DT_UNKNOWN = 0,
DT_FIFO = 1, // 命名管道
DT_CHR = 2, // 字符设备
DT_DIR = 4, // 目录
DT_BLK = 6, // 块设备
DT_REG = 8, // 常规文件
DT_LNK = 10, // 符号链接
DT_SOCK = 12, // 套接字
DT_WHT = 14
};

注意:部分 linux 文件系统,例如 xfs 不支持 d_type,当使用 d_type 时,所有文件/目录的 d_type 会一直为空,即 0(DT_UNKNOWN)。无法判断文件类型,所以需要 stat 函数。

1. 读取目录下的所有文件名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const char* dir_str = "/proc";
DIR* dir = opendir(dir_str);
if (dir == NULL) {
perror("open dir err: ");
exit(-1);
}
struct dirent* ptr;
while ((ptr = readdir(dir)) != NULL) {
if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
continue;
} else if (ptr->d_type & DT_REG) {
// file
printf("file: %s\n", ptr->d_name);
} else if (ptr->d_type & DT_LNK) {
// link file
printf("link file: %s\n", ptr->d_name);
} else if (ptr->d_type & DT_DIR) {
// dir
printf("dir: %s\n", ptr->d_name);
}
}
closedir(dir);

查看更多

undefined

一、变参函数

实现可变参数需要借助标准 C 中的一些技术

  • va_list 指向参数列表的指针
  • va_start 初始化 va_list 并使其指向指定参数之后的参数位置
  • va_arg 从参数列表中获取下一个参数(获取时需指定参数类型,这样底层才能正确计算出内存范围)
查看更多

undefined

module 的使用

默认情况下,GOPATH是不支持go modules 的。在 go env 中查看。设置 export GO111MODULE=on

使用goland 打开项目或创建项目的时候,需要设置 go modules 为 enable。

使用 go mod init module_name ,比如 go mod init github.com/objcoding/testmod

go mod 中初始化第一行就是项目的依赖路径,通常来说该地址就是项目的仓库地址,所以需要项目包的地址都填写这个地址,无论是内部之间引用还是外部引用。

在项目启用啦 go modules 之后,引用包必须跟 go mod 文件第一行包名一样,依赖的包都会保存在 ${GOPATH}/pkg/mod 文件夹中。

查看更多