linux实现循环移位,Linux C下面遇到的坑

xshell与Linux系统文件编码的不同所造成的乱码问题,如果不能修改Linux的编码,那么可以试着修改xshell的编码。

addr.sin_port与Int并不是同一种结构,htons就是用来进行网络字节顺序和主机字节顺序转换的。

一定要看好括号的范围

例如:connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length)<0

错误:connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length<0)

例如:(fd=open(filebag.data, O_WRONLY|O_CREAT)) < 0

错误:(fd=open(filebag.data, O_WRONLY|O_CREAT) < 0)还是不会报错,但是最后fd会为0

虽然并不会报错,但是connect就会一直失败,erron会提示参数错误。

erron全局错误变量可以起到错误提示作用,包含于erron.h中。

变量名要与类名区分开来,标准的命名规则还是很有用的。

sdout会有缓存,printf中的内容并不会及时输出,这时可以加上"\n"或者fflush(sdout),就会强制刷新缓存区。

open与fopen有很大区别,返回值和参数都不一样。

open函数还有第四个参数,用来设置创建的文件的权限。有时候不设置没问题,有时候有问题,所以还是设置一下吧。

test是Linux的一个指令,所以$test没有输出,而$./test指明了为文件,所以可以输出。

直接在case后面定义变量会报错,如果不加这种限制,可能就会出现这种情况 :

case 1:

int x;

case 2:

x = 0;

因为case的域实际上是连在一起的,所以在编译器编译时,并不会认为有错误,但是程序在实际运行时,直接跳到了case2,那么x明明没有被定义,却被使用,就会出错。解决方法:在case后面加上花括号。

C里面并没有bool类型

C中的if非零为真,零为假。指针实际上也为一个int数值,所以可以进行真or假判断。

FILE * 类型的指针实际上是指向一个结构体。

perror(s)会优先输出s,再根据errno的值输出错误信息。

只有char类型数组才需要‘/0’

区分开'r'与"r" 前者其实为int类型,而后者可以视为一个指针。fopen的参数就应该使用"r"

区分开"\0"与'\0',前者是一个指针,后者是一个字符。但是如果使用"\0",会警告将指针赋给整数,而有时候结果却并不会出错。使用%d输出"\0",会输出符号+部分数字。或许是因为char的长度为1,Int的长度为4??

malloc地址一定要memset,要不然错误free会报错。

只要使用malloc为char *ptr申请哪怕1个字节的空间,你就可以将一个很长的字符串给他,而且还可以正常输出,但是free的时候会报错。

epoll_event.data 是一个union,fd和ptr只能选一个!

在epoll_ctl的时候,一定要确保epoll_event.data和epoll_event.events的值是正确的。

typedef struct queryStruct

{

char type[10];

char id[10];

char name[30];

char pass[30];

char *sendMess;

} queryDataStruct;

//用来向线程中传入相关信息

typedef struct threadStruct

{

int epollfd;

int clienfd;

struct epoll_event stev;

queryDataStruct *query;

} threadDataStruct;

//教训:向epoll_event stev.events中加入了数据,但是却没有管stev.data.ptr,所以虽然开头用

epoll_ctl(epollfd, EPOLL_CTL_ADD, clienfd, &(events[i]));

//添加成功,因为前面把threadDataStruct的指针给了events[i].data.ptr

//但是后面,在其他函数中,只能使用自己的结构体作为参数

epoll_ctl(threadData->epollfd, EPOLL_CTL_DEL, threadData->clienfd,&(threadData->stev));

//又没有往threadData->stev.data.ptr中放值,造成地址类型的错误

不能把一个公用的全局指针从epoll读取块直接拿到epoll写入块中使用。因为读取块是用的clienfd=1,而写入块可能就是用的clienfd=22。一个客户端连接时没有影响,多个客户端连接,应该就会出现数据误传的情况。

结构体可以直接包含非自身结构体变量。

只要是C风格的char字符串,那么最后必然会带上一个\0。而strlen计算,碰到\0就会停止计数。所以在send数据,要使用sizeof(但是对指针只计算指针的大小,不计算数据大小)或者strlen(str)+1。

epoll事件使用ET读写模式,在服务端将缓存区数据读取完毕之后,当缓存区有新数据可读时,又会再次触发事件通知。ET只通知一次,指的是服务端自己缓存区取得一次数据(即有数据,然后读完算一次),而和客户端怎么取的没有关系。如果在处理读事件时,将数据的读取交给另外的线程处理,主线程继续循环处理监听到的events事件,那么就可能出现一个fd被放入多个线程的情况。这时就要在结构体中加一个判断变量,在将其放入线程前判断其前面是否已经被放入。

send函数的参数如果超过发送数据的实际大小,那么就会发送重复的数据。所以最好将参数设置为数据的大小。

send函数每次发送都会从参数的开头地址发送,recv接收时也是这样。(和文件的读取不一样)。所以C在循环读取数据并放入同一个字符数组中时,记得移动指针。

sprintf函数的格式化功能还是挺强的,使用时要把参数确定好。例如:

sprintf(cLen, "%-10d", iLen); //位数不够时用\0填充

sprintf(cLen, "%d", iLen); //位数不够时用' '填充

例如下面这样:

char *str1;

char *str2;

char *str3;

str1 = (char *)malloc(11);

str2 = (char *)malloc(100);

strcpy(str1, "UUUUUUUUUU");

strcpy(str2, "QQQQQQQQQQQQQQQQQQQQQQQ");

str3 = str1 + 5;

str3 = str2;

printf("str1 = %s\n", str1);

return 0;

是没有用的,因为以前学习数据结构时,经常使用例如

/*

struct queue

{

struct queue *next;

int data;

}*/

struct queue *ptr = head;

ptr->next = 一个指针

head->next = 一个指针 //这两个是等效的

ptr = 一个指针

head = 一个指针 //这两个是不一样的

原因:head->next是head自身包含的地址指向的一段内存,而head则是自身包含的地址。当ptr = head后,并不是说现在ptr就和head等价了(大学四年一直误以为此),只是prt和head中包含的地址是一样的,当你用ptr->next进行操作的时候,是操作ptr包含的地址指向的空间,所以无论是对ptr还是对head进行操作,都是等同的。但是在对ptr和head进行操作的时候,你操作的就是两个完全不同的变量了,所以操作不等同。ptr = head,只是ptr和head中保存的地址一样了,而不是ptr本身的地址和head一样了。

就好像你把甲的仓库钥匙复制给了乙一份,那么甲和乙操作的仓库就是同一个仓库了,这时候你把乙的钥匙换了,那么甲的钥匙并不会跟着乙的一起变化。

可以使用realloc实现动态数组,虽然感觉并没有什么用。另外,为了减少realloc的次数,在分配空间和减少空间时,都可以预分配一定空间。

char类型数组后面一定要有一个\0,如果你要用一个数组从一个字符串中复制出10个值,那么这个数组的大小起码要为11,如果大小为10,那么再你输出这个数组时,有可能连带输出后面地址的值。

能不用malloc就不要用,能不用多线程就不要用。

指针定义和free后指NULL是一个好习惯。

str[i++]和str[++i]也遵循先给后加和先加后给原则,即中括号并没有小括号的作用,它并没有优先级。

由于二进制不能精确表示小数,所以double和float有时候并不是精确的,只是在printf时会输出近似值。但是如果使用int强制转换,会完全丢失小数部分,然后就表现为比原数小1。解决办法:int(math + 0.5)。

C语言没有默认参数。

以前从来没有注意过,在C中不能单独输出一个中文字符串中的一个中文字符。一个中文字符占两个char。中文字符最小都是一个长度为2的字符串?

const struct *head,那么head中变量值都不可以改变。

math>>1 将math变为二进制,然后左移1位,位数不足补零。最好不要对有符号数使用,移位之后的位数不能超过有效位数。采用math+math>>1,符合条件的情况下等同于1.5*math,但是速度要块很多。

无锁数据结构的基本操作CAS,将一个变量的值与A值比较,如果相等,那么将变量的值变为B值。没有加锁和解锁过程,性能影响较小,避免死锁和活锁的情况。但是可能会产生ABA问题。

C语言接口。一组回调函数(函数指针)+函数上下文(指向一个或一组数据)。根据自己的需要让接口内的函数指针指向不同的函数,而调用是统一调用接口的。

C语言容器。其实也是一个接口,也就是说也有一组回调函数和函数上下文。先实现容器接口,然后再用实现了的容器实现需要的结构。原来是用双向链表和动态数组分别实现队列的接口,那么抽象出容器后,我们先用双线链表和动态数组实现容器,然后再用容器实现队列。虽然中间多了一步,但是下次要实现栈的是时候,就可以直接使用容器直接来实现了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值