1.   #define LOWER(c)            (unsigned char)(c | 0x20)

换成小写

2.   gcc -Wall -Werror //告警当成 错误来处理

3.  gcc -Ox  //优化等级,一般debug搞成0, release搞成3

4. 一种处理错误码的方法

不说什么,贴代码

#include <stdio.h>

#define HTC_ERROR_MAP(xx)    \
xx(OK, "SUCCESS")\
xx(INVALID_VERSION, "invalid protocal version")\
xx(INVALID_STATUS, "invalid protocal status")\ #define HTC_ERRNO_GEN(n,s) HTC_##n, #define HTC_ERRSTR_GEN(n,s) {"HTC_"#n,s}, enum HTC_ERRNO
{
HTC_ERROR_MAP(HTC_ERRNO_GEN)
}; static struct
{
const char* name;
const char* desc;
} protocal_err[] = {HTC_ERROR_MAP(HTC_ERRSTR_GEN)}; int
main()
{
enum HTC_ERRNO errno=HTC_OK;
printf("name = [%s], desc = [%s]\n", protocal_err[errno].name, protocal_err[errno].desc);
return 0;
}

这里,使用了宏来巧妙的处理了错误码的枚举和错误码详细信息

使用的技巧:## 宏连接两个宏定义, #连接字符串

5. gcc -DXXXXX

用来定义宏,一般用来写DEBUG宏

CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_DEBUG=1

6. 封装数据结构,只有外部可见的数据结构才放在头文件中声明,定义仍然放在.c文件中

7. Makefile如果想取得文件夹下全部文件

$(wildcard $(PATH)/*.c)

8..c转成.o文件

$(xxx:%.c=%.o)

即可

例子:

$(ALLFILES:%.c=%.o)

9. 使用void* 来适配任何类型数据

void* data = (void*) 128;

10. #define ULLONG_MAX  (uint64_t-1)

uint64_t  为 typedef unsigned long int

11. struct in_addr ip地址的数据结构

  保存一个属性,s_addr,一般是转换成网络序格式的32位ip地址

可以使用inet_aton()函数来进行转换,

12. printf 打印16进制的方法

%X

%08X 长度为8的16进制

13. #error

该语法报用户自定义的错误信息

14. socket(AF_INET,  SOCK_STREAM, 0)

15. bind

  bind需要注意的是:struct sockaddr_in中的sin_port sin_addr都是网络序的

  bind第二个参数为了兼容各种sockaddr数据结构,使用struct sockaddr定义参数,需要转换格式

  所以 saddr.sin_family = AF_INET

    saddr.sin_port=htons(xxxx)

    struct addr_in addr;

    bzero(&addr, sizeof(addr));

    inet_pton(AF_INET, "xx,xx,xx,xx", &addr);

    saddr.sin_addr= addr;

    bind(AF_INET, (struct sockaddr*)(&saddr), INET_ADDRSTRLEN);(IPV4的长度)

16. 在Accept 函数ok后,应该关掉socket返回的fd。结束accept,需要关闭accept函数返回的fd

17.  server  socket -> bind->listen-> accept->fork   child -> close(sockfd)->>read--->close

                          parent ->close(connectfd) ->>accet->>

/**

**/

#include <stdio.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <strings.h> #define USAGE "exec method: ./server\n" #define IP_ADDR "127.0.0.1"
#define PORT 2013
#define IPV4 AF_INET
#define BACKLOG 50
//#define IPV4_ADDR_LEN INET_ADDRSTR_LEN #define EXIT_MSG "bye\n" #define handle_error(xx)\
do{perror(xx); exit(EXIT_FAILURE);}while()\ static void usage()
{
printf(USAGE);
} static void proc_msg(int sockfd, int connectfd, pid_t name)
{
char buf[];
int readlen=;
bzero(buf, sizeof(buf));
printf("accept success...\n");
printf("server start to work...\n");
close(sockfd);
for(;;)
{
bzero(buf, sizeof(buf));
readlen = recv(connectfd, buf, , );
if(readlen >)
{
printf("[%d] receive msg : %s", name,buf);
if(strncmp(EXIT_MSG, buf) == )
break;
}
if(readlen <= )
{
perror("fail read ...");
break;
}
} } int main(int argc , char* argv[])
{
int sockfd = ;
int connectfd =;
struct in_addr inaddr;
struct sockaddr_in skaddr;
socklen_t len;
pid_t child = ;
char buf[];
int readlen = ;
if(argc >)
{
usage();
return ;
} bzero(&inaddr, sizeof(struct in_addr));
bzero(&skaddr, sizeof(struct sockaddr_in)); skaddr.sin_family = IPV4;
if(inet_pton(IPV4, IP_ADDR, &(skaddr.sin_addr)) == )
handle_error("IP address is not avialabel..."); skaddr.sin_port = htons(PORT); //scoket
sockfd = socket(IPV4, SOCK_STREAM, );
//bind
if( bind(sockfd, (struct sockaddr*)(&skaddr), sizeof(struct sockaddr_in)) != )
handle_error("bind fd failed...");
//listen
if(listen(sockfd, BACKLOG) != )
handle_error("listen fd failed..."); len = sizeof(struct sockaddr_in); for(;;)
{
if((connectfd =accept(sockfd, (struct sockaddr*)(&skaddr), &len)) >)
{
if((child = fork()) == )
{
proc_msg(sockfd, connectfd, child);
close(connectfd);
}
close(connectfd);
}
} return ;
}

client    socket->connect->

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <strings.h>
#include <unistd.h>
#include <string.h> int main()
{
int sockfd = ;
struct sockaddr_in skaddr;
char buf[]; bzero(&skaddr, sizeof(skaddr));
skaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &(skaddr.sin_addr));
skaddr.sin_port = htons(); //socket
sockfd = socket(AF_INET, SOCK_STREAM, );
//connect
connect(sockfd, (struct sockaddr*)(&skaddr), sizeof(skaddr)); //send
for(;;)
{
bzero(buf, sizeof(buf));
if(fgets(buf, , stdin) != NULL)
{
send(sockfd, buf, strnlen(buf, ), );
}
}
sleep();
close(sockfd);
}

  18. killall -HUP xxxx 杀掉进程,进程名

19. 僵死进程

子进程已终 止,父进程尚未对其执行wait操作,子进程会转入“僵死”状态。内核为“僵死”状态的进程保留最少的信息量(进程标识,终止状态,资源使用信息),过后 父进程执行wait时可以获取子进程信息。只要僵死的进程不通过wait从系统中移去,它将会占据内核进程表中的一个栏位。如果进程表被填满,内核将不能 再产生新进程。如果父进程已终止,它的僵死子进程将由init进程收养,并自动执行wait将它们移去。

请对子进程进程wait操作。

20.

信号集是一个位向量,其中每一位对应着linux系统的一个信号。可使用如下函数对信号集进行处理:

#include <signal.h>

int sigemptyset(sigset_t * set);

int sigfillset(sigset_t * set);

int sigaddset(sigset_t * set);

int sigdelset(sigset_t * set);

sigemptyset将一个信号集清空;sigfillset将信号集的所有位置位;sigaddset函数将参数signo指定的信号所对应的位设置为1;sigdelset将signo的对应位设置为0。

21. EINTR

注意处理EINTR错误,errno返回时EINTR的时候,说明被信号中断导致的错误

22. signal是软中断

23. sigaction.sa_handler= func;

24. 在处理SIGCHLD信号的函数中,while(waitpid(-1, &status, WNOHANG) > 0)来处理子进程的退出

25. I/O复用的概念,想象一下这种场景,进程阻塞在读取I/O上,但是另一个I/O也在等待操作,那么这怎么办呢,这时候就需要用到I/O复用的概念了。

26.

select 函数,用来等待多个I/O的读写状态,不再需要的等待一个I/O而阻塞了

27.   socket连接握手

  client --> seq k ---> server

  client<---- seq J ack k+1 <-----server

client ----> ack j+1---->server

三次的消息flag分别是: seq, seq ack, ack     02, 12 , 10

28. close 和shutdown的区别,

  共享套接字的情况下,close只是共享个数减 1, 只有到个数为零的时候,才会关闭套接字。

  而shutdown是等缓存中数据都取完后,直接关闭套接字,并不关心有多少个共享存在。但是套接字还是存在的,还需要用close来关闭

29.  TIME_WAIT状态,是socket已经关闭后,保持的状态,一般是2MSL的时长

30.  CLOSE_WAIT是被动关闭的一端,收到close后,没有close的状态

应该处理这种情况

if(recv(clientArray[i], recvBuf, 1024, 0) == 0)
{

#if __DEBUG__
printf("process CLOSE_WAIT status\n");
#endif

close(clientArray[i]);
  close(sockfd);
  index--;
}

31. linux kernel经常看到宏

#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

#define container_of(ptr, type, member)                 \
({                                                        \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);\
    (type *)( (char *)__mptr - offsetof(type,member) ); \
})

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

offsetof宏是用来找到结构中,某个成员的偏移量

container_of 宏是根据成员的指针找到容器的指针

整个宏就是根据成员的指针找到容器的指针,ptr入参为成员的指针

32.  inline使用

inline函数不要超过10行代码,且不能包含循环、switch、if语句。

在一个c文件中定义的inline函数是不能在其它c文件中直接使用,google推荐把inline函数定义在**-inl.h头文件中。

不要过度使用inline函数定义,尤其对大函数来说。

c语言技巧--长期更新的更多相关文章

  1. [原创][FPGA]Quartus实用小技巧(长期更新)

    0. 简介 在使用Quartus软件时,经常会时不时的发现一些小技巧,本文的目的是总结所查阅或者发现到的小技巧,本文长期更新. 1. Quartus中的模板功能 最近在Quartus II的菜单里找到 ...

  2. Java代码优化(长期更新)

    前言 2016年3月修改,结合自己的工作和平时学习的体验重新谈一下为什么要进行代码优化.在修改之前,我的说法是这样的: 就像鲸鱼吃虾米一样,也许吃一个两个虾米对于鲸鱼来说作用不大,但是吃的虾米多了,鲸 ...

  3. 嵌入式开发中常见3个的C语言技巧

    Hey,大家好!我是CrazyCatJack.今天我来说几个在嵌入式开发中常用的C语言技巧吧.也许你曾经用过,也许你只是见到过但是没有深入理解.那么今天好好补充下吧^_^ 1.指向函数的指针 指针不光 ...

  4. iOS-工作经验+资料分享(长期更新)

    在此记录工作中的一些经验和技术资料 长期更新 欢迎各位业内朋友指正.交流技术上的问题 0.苹果开发联盟电话 4006 701855 1.轻易不用使用tableViewController,因为改变他自 ...

  5. Ubuntu16.04系统美化、常用软件安装等,长期更新

    Ubuntu16.04系统美化.常用软件安装等,长期更新 IT之家啊 18-09-0915:00 因为我个人偏向于玩VPS.服务器之类的东西,所以一般我都是用CentOS.不过对于桌面版的Linux, ...

  6. Spring MVC & Boot & Cloud 技术教程汇总(长期更新)

    昨天我们发布了Java成神之路上的知识汇总,今天继续. Java成神之路技术整理(长期更新) 以下是Java技术栈微信公众号发布的关于 Spring/ Spring MVC/ Spring Boot/ ...

  7. fastadmin 后台管理框架使用技巧(持续更新中)

    fastadmin 后台管理框架使用技巧(持续更新中) FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架,具体介绍,请查看文档,文档地址为:https://doc. ...

  8. python的多版本安装以及常见错误(长期更新)

    (此文长期更新)Python安装常见错误汇总 注:本教程以python3.6为基准 既然是总结安装过程中遇到的错误,就顺便记录一下我的安装过程好了. 先来列举一下安装python3.6过程中可能需要的 ...

  9. 项目中解决实际问题的代码片段-javascript方法,Vue方法(长期更新)

    总结项目用到的一些处理方法,用来解决数据处理的一些实际问题,所有方法都可以放在一个公共工具方法里面,实现不限ES5,ES6还有些Vue处理的方法. 都是项目中来的,有代码跟图片展示,长期更新. 1.获 ...

随机推荐

  1. Cocos2d-x 3.1.1 学习日志9--一“上一下其乐无穷”游戏开发系列一

    下载地址:http://app.mi.com/search?keywords=%E4%B8%80%E4%B8%8A%E4%B8%80%E4%B8%8B%E5%85%B6%E4%B9%90%E6%97% ...

  2. /dev/tty 与 /dev/pts

     打开3个bash会话窗口  [root@server1 fd]# cd /proc/7489/fd[root@server1 fd]# ll总用量 0lrwx------ 1 root root 6 ...

  3. 8 Pratical Examples of Linux “Touch” Command--reference

    In Linux every single file is associated with timestamps, and every file stores the information of l ...

  4. WPF学习之资源-Resources

    WPF学习之资源-Resources WPF通过资源来保存一些可以被重复利用的样式,对象定义以及一些传统的资源如二进制数据,图片等等,而在其支持上也更能体现出这些资源定义的优越性.比如通过Resour ...

  5. Bash判断文件夹(目录)是否存在

    #!/bin/bash if [ -d DirName ]; then echo 'Dir exist' else echo 'Dir not exist' fi

  6. 服务器端PHP多进程编程

    待更新 版权声明:本文为博主原创文章,未经博主允许不得转载.

  7. HTML5吧

    一.为了能使IE9以下的IE浏览器也能支持html5的标签,所以首先得在文档头部用条件注释的方法引入那段著名的代码. 1 2 3 <!--[if lt IE 9]> <script ...

  8. Reporting Services 2: 参数化报表

    http://www.cnblogs.com/waxdoll/archive/2006/07/16/452467.html

  9. Twisted介绍

    Twisted诞生于2000年初,作者为Glyph,目的是为了开发网络游戏. Twisted的历史 Glyph开始采用Java多线程,来开发Twisted Reality,结果多线程使得开发变得复杂, ...

  10. Error Domain=com.google.greenhouse Code=-102

    *** Terminating app due to uncaught exception 'com.google.greenhouse', reason: 'Error Domain=com.goo ...