1.stat函数
原型:int stat(const char *pathname, struct stat *statbuf);
功能:取得指定文件的文件属性,文件属性存储在结构体stat里。
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
参数:
pathname:文件名
statbuf:文件属性
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
2.offsetof宏
原型:#define offsetof(TYPE, MEMBER) ((int)&((TYPE *)0)->MEMBER)
功能:获取结构体中MEMBER成员的偏移
头文件:
#include <stddef.h>
3.container_of宏
原型:#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
功能:返回结构体的首地址
参数:
ptr:表示结构体中member的地址
type:表示结构体类型
member:表示结构体中的成员
说明:
第一部分:const typeof( ((type *)0)->member ) *__mptr = (ptr);
通过typeof定义一个member指针类型的指针变量__mptr,(即__mptr是指向member类型的指针),并将__mptr赋值为ptr。
第二部分: (type *)( (char *)__mptr - offsetof(type,member) )
通过offsetof宏计算出member在type中的偏移,然后用member的实际地址__mptr减去偏移,得到type的起始地址,即指向type类型的指针。
#include <stdio.h>
#include <stdlib.h>
#define NAME_STR_LEN 16
#define offsetof(type, member) (size_t)&(((type*)0)->member)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
typedef struct StuData
{
int id;
char name[NAME_STR_LEN];
int age;
}studata;
int main()
{
unsigned int off_set = 0;
off_set = offsetof(studata, id);
printf("id offset: %d\n",off_set);
off_set = offsetof(studata, name);
printf("name offset: %d\n",off_set);
off_set = offsetof(studata, age);
printf("age offset: %d\n",off_set);
studata*stu = (studata*)malloc(sizeof(studata));
stu->age = 15;
studata*ptr = container_of(&(stu->age), studata, age);
printf("stu age:%d\n", ptr->age);
printf("stu addr:%p\n", stu);
printf("ptr addr:%p\n", ptr);
free(stu);
stu = NULL;
return 0;
}
id offset: 0
name offset: 4
age offset: 20
stu age:15
stu addr:0x11dd420
ptr addr:0x11dd420
4.getline函数
原型:ssize_t getline(char **lineptr, size_t *n, FILE *stream);
功能:从输入流中读取一行字符,读到终止符时会将’0’存入结果缓冲区中,作为输入的终止。三种情况终止:
1)到文件结束,2)遇到函数的定界符,3)输入达到最大限度。
头文件:#include <stdio.h>
参数:
lineptr:指向存放该行字符的指针,如果是NULL,则有系统帮助malloc,请在使用完成后free释放。
n:如果是由系统malloc的指针,请填0
stream:文件描述符
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t readLen;
fp = fopen("./test1.c", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((readLen = getline(&line, &len, fp)) != -1)
{
printf("read data length %zu \n", readLen);
printf("%s", line);
}
if (line)
free(line);
fclose(fp);
return 0;
}
注:
%z 是用来输出 size_t 类型
5.#和##的学习
1)##连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。
以下为不允许:
起始位置:##token1##token2
结束位置:token1##token2##
#define A1(name, type) type name_##type##_type 或
#define A2(name, type) type name##_##type##_type
A1(a1, int); /* 等价于: int name_int_type; */
A2(a1, int); /* 等价于: int a1_int_type; */
2)#符是把传递过来的参数当成字符串进行替代
6.赋值语句和赋值表达式的区别
a = b 这是一个赋值表达式;
而a = b;这是一个表达式语句(Expression statement,它是语句而不是表达式),它包含了赋值表达式 a = b。
if((a=b)>0) {} 按语法规定if后面的( )内是一个条件。现在在x的位置上换上一个赋值表达式“a=b”,其作用是:先进行赋值运算(将b的值赋给a),然后判断a是否大于0,如大于0,执行{}。在if语句中的“a=b”不是赋值语句而是赋值表达式,这样写是合法的。
不能写成 if((a=b;)>0) {} 因为在if的条件中不能包含赋值语句
7.sprintf函数
原型:int sprintf(char *str, const char *format, …)
功能:发送格式化输出到 str 所指向的字符串。
参数:
str:这是指向一个字符数组的指针,该数组存储了 C 字符串。
format:这是字符串,包含了要被写入到字符串 str 的文本。
返回值:
如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。
8.strspn()函数
原型:size_t strspn(const char *str1, const char *str2)
功能:检索字符串 str1 中第一个不在字符串 str2 中出现的字符下标。
头文件:#include <string.h>
参数:
str1:要被检索的 C 字符串。
str2:该字符串包含了要在 str1 中进行匹配的字符列表。
返回值:
返回字符串s开头连续包含字符串accept内的字符数目。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *a = "abcdefg0123455adcd";
char *b = "adabc";
int pos = 0;
pos = strspn(a,b);
printf("%d\n", pos);
return 0;
}
4
函数原型:
int strspn(const char *s,const char *accept)
{
const char *p;
const char *a;
int count = 0;
for(p = s; *p != '\0'; ++p)
{
for (a = accept; *a != '\0'; ++a)
{
if (*p == *a)
break;
}
if (*a == '\0')
return count;
++count;
}
return count;
}
9.strtok_r函数
原型:char *strtok_r(char *str, const char *delim, char **saveptr);
功能:按某个字符来分割字符串。
头文件:#include <string.h>
参数:
str是传入的字符串。需要注意的是 :第一次使用strtok_r之后,要把str置为NULL
delim指向依据分割的字符串。常见的空格“ ” 逗号“,”等
saveptr保存剩下待分割的字符串
返回值:排在前面的 被分割出的字串,或者为NULL
注:str不能指向常量指针,不然出现程序崩溃
char *pchSrc = "this is c language";
char chBuffer[102] ;
char *pchDilem = " ";
char *pchStrTmpIn = NULL;
char *pchTmp = NULL;
strncpy(chBuffer,pchSrc ,sizeof(chBuffer) - 1);
pchTmp = chBuffer;
while(NULL != ( pchTmp = strtok_r( pchTmp, pchDilem, &pchStrTmpIn) ))
{
printf("\n pchTmp[%s] pchStrTmpIn[%s]\n",pchTmp,pchStrTmpIn);
pchTmp = NULL;
}
10.access函数
原型:int access(const char* pathname, int mode);
功能:判断文件的作用
头文件:#include<unistd.h>
参数:
pathname 是文件的路径名+文件名
mode:指定access的作用,取值如下
F_OK 值为0,判断文件是否存在
X_OK 值为1,判断对文件是可执行权限
W_OK 值为2,判断对文件是否有写权限
R_OK 值为4,判断对文件是否有读权限
注:后三种可以使用或“|”的方式,一起使用,如W_OK|R_OK
返回值:
0:表示成功
-1:表示失败
if(access(name,F_OK)==0){
printf("文件存在\n");
if(access(name,R_OK|W_OK)==0){
printf("文件可读可写\n");
}else
printf("文件不可读或不可写\n");
if(access(name,X_OK)==0){
printf("文件可执行\n");
}else{
printf("文件不可执行\n");
}else{
printf("文件不存\n")
}
11.struct hostent结构体
struct hostent
{
char *h_name; //正式主机名
char **h_aliases; //主机别名
int h_addrtype; //主机IP地址类型:IPV4-AF_INET
int h_length; //主机IP地址字节长度,对于IPv4是四字节,即32位
char **h_addr_list; //主机的IP地址列表
};
#define h_addr h_addr_list[0] //保存的是IP地址
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
char *ptr, **pptr;
struct hostent *hptr;
char str[32] = {0};
ptr = argv[1];
if((hptr = gethostbyname(ptr)) == NULL)
{
printf("gethostbyname error: %s\n", ptr);
return 0;
}
printf("official hostname:%s\n", hptr->h_name); //主机规范名
for(pptr = hptr->h_aliases; *pptr != NULL; pptr++) //将主机别名打印出来
printf("alias: %s\n", *pptr);
switch(hptr->h_addrtype) //根据地址类型,将地址打印出来
{
case AF_INET:
case AF_INET6:
pptr = hptr->h_addr_list;
for(; *pptr != NULL; pptr++) //将得到的所有地址打印出来
{
printf("address: %s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); //inet_ntop: 将网络字节序的二进制转换为文本字符串的格式
printf("first address: %s\n", inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str)));
}
break;
default:
printf("unkown address type\n");
break;
}
return 0;
}
12.prctl()函数
原型:int prctl ( int option,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5 )
功能:设置进程属性
头文件:#include <sys/prctl.h>
参数:
返回值:
0:表示成功
-1:表示失败
示例:
进程重命名代码
prctl(PR_SET_NAME, “process_name”, NULL, NULL, NULL);
第一个参数是操作类型,指定PR_SET_NAME,即设置进程名
第二个参数是进程名字符串,长度至多16字节
13.assert函数
原型:void assert( int expression );
功能:计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行
头文件:#include <assert.h>
14.unlink函数
原型 :int unlink(const char * pathname);
功能:unlink()会删除参数pathname 指定的文件. 如果该文件名为最后连接点, 但有其他进程打开了此文件, 则在所有关于此文件的文件描述词皆关闭后才会删除. 如果参数pathname 为一符号连接, 则此连接会被删除。
参数:文件名
返回值:成功则返回0, 失败返回-1, 错误原因存于errno。
errno 错误值:
1)EROFS 文件存在于只读文件系统内。
2)EFAULT 参数pathname 指针超出可存取内存空间。
3)ENAMETOOLONG 参数pathname 太长。
4)ENOMEM 核心内存不足。
5)ELOOP 参数pathname 有过多符号连接问题。
6)EIO I/O 存取错误。
15.tail -f 日志动态新增。