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. Linux 性能优化之 IO 子系统 系列 图

    http://blog.sina.com.cn/s/articlelist_1029388674_11_1.html Linux 性能优化之 IO 子系统(一) 本文介绍了对 Linux IO 子系统 ...

  2. MapReduce链接作业

    对于简单的分析程序,我们只需一个MapReduce就能搞定,然而对于比较复杂的分析程序,我们可能需要多个Job或者多个Map或者Reduce进行计算.下面我们来说说多个Job或者多个MapReduce ...

  3. Day01 - Python 基础介绍

    1 Python 简介 1.1 Python 的由来 Python的创始人:吉多·范罗苏姆(Guido van Rossum) 1989年,吉多·范罗苏姆为了在阿姆斯特丹打发圣诞节假期时间,开发的一个 ...

  4. JSPatch 成长之路

    在这次 GMTC 大会上,我见到了 JSPatch 的作者 bang.在这之前我就和他在网上认识并聊过很多次,bang 也在这个公众号上投稿发表了多篇关于 JSPatch 的文章,包括:JSPatch ...

  5. 本地nginx多域名映射

    前言: 工作两年多了,一直感觉技术上没有太大的长进,好多东西感觉会但是给别人讲起来的时候又感觉和没学过一样.以后希望能坚持写博客,把看过的东西都一点一滴积累下来.言归正传,今天要说的是nginx与ho ...

  6. angularjs filter cut string

    angular.module('App.controllers.MyCtrl', []) .controller('MyCtrl', function (my) {}) .filter('cut', ...

  7. VS2015+TFS2015源代码管理

    使用Visual Studio连接TFS

  8. php 5.3起弃用session_register

    最近下了dedecms V5.7时,在登陆后台时,用户名和密码也没错,就是跳转不走,进不了后台管理页面,追踪了好久才发现根目录/include/userlogin.class.php中289行左右的位 ...

  9. ionic 项目分享No.2——简化版【转】

    写在文章前:由于最近研究ionic框架,深感这块的Demo寥寥可数,而大家又都藏私,堂堂天朝,何时才有百家争鸣之象,开源精神吾辈当仁不让!                                ...

  10. P2P金融的概念理解

    P2P金融又叫P2P信贷.其中,P2P是 peer-to-peer 或 person-to-person 的简写, 意思是:个人对个人. P2P金融指个人与个人间的小额借贷交易,一般需要借助电子商务专 ...