一些LinuxC的小知识点(一)
以下代码在Federo9上试验成功。
一、格式化输入16进制字符串
- printf("Format:%.2x\n",);
输入结果:
二、测试各类型的占用的字节数
- int main(int argc, char *argv[])
- {
- int OutputHex = ;
- unsigned char aValue=;
- char Buffer[];
- int len=sprintf(Buffer, OutputHex ? "%.2X " : "%c", aValue);
- printf("Len:%d Format:%s\n",len,Buffer);
- printf("Size Of char:%d\n",sizeof(char));
- printf("Size Of unsigned char:%d\n",sizeof(unsigned char));
- printf("Size Of int:%d\n",sizeof(int));
- return EXIT_SUCCESS;
- }
输入结果:
三、使用getopt函数来获取参数
当我们运行Linux下的C语言程序的时候,就可以非常方便地用getopt()这个函数将main参数中的argv提取出来,按需进行处理。函数的使用见以下代码段。
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- int main(int argc, char *argv[])
- {
- int opt;
- while((opt = getopt(argc, argv, ":if:lr")) != -) {
- switch(opt) {
- case 'i':
- case 'l':
- case 'r':
- printf("option: %c\n", opt);
- break;
- case 'f':
- printf("filename: %s\n", optarg);
- break;
- case ':':
- printf("option needs a value\n");
- break;
- case '?':
- printf("unknown option: %c\n", optopt);
- break;
- }
- }
- for(; optind < argc; optind++)
- printf("argument: %s\n", argv[optind]);
- exit();
- }
四、exit()和_exit()函数
1、_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核。
2、exit中的参数exit_code为0代表进程正常终止,若为其他值表示程序执行过程中有错误发生。
五、用fprintf实现printf
大家可以通过以下代码看看两者的异同。
- #include <stdio.h>
- int main(void){
- printf("Hello world using printf\n");
- fprintf(stdout, "Hello world To stdout\n");
- fprintf(stderr, "Hello world To stderr\n");
- }
- stdout和stderr都是打印在屏幕的,因为标准错误输出流对象(stderr)就是定义为屏幕
输出结果:
小记:
- 关于 stdin、stdout、stderr 的说明如下:
stdout(Standard Output Stream)标准输出
stdin(Standard Input Stream)标准输入
stderr(Standard Error Output)标准错误输出
默认情况下,标准输入(stdin)指的从键盘上读数据,而标准输出(stdout)和标准错误输出(stderr)是指屏幕
六、捕捉Esc按键
捕捉其他按键的程序跟这个差不多,总的思路就是通过判断键盘扫描码进行对应的处理。
- #include <stdio.h>
- int main ( void )
- {
- unsigned char aValue;
- printf ( "Enter a Char\n" );
- aValue = getchar();
- if ( aValue == '\x1b' )
- {
- printf ( "Esc pressed %c\n",aValue );
- }else
- {
- printf ( "Esc Not pressed%c\n",aValue );
- }
- }
结果:
七、避免getchar()读入用于结束输入的换行符
- #include <stdio.h>
- int main ( void )
- {
- unsigned char aValue;
- do{
- printf ( "Enter a Char\n" );
- do{
- aValue = getchar();
- }while(aValue=='\n' );//避免读入\n
- if ( aValue == '\x1b' )
- {
- printf ( "Esc pressed.\t \n" );
- }else
- {
- printf ( "Esc Not pressed.\t%c Pressed\n",aValue );
- }
- }while(aValue!='q' );//读到q的时候,退出
- }
八、如果stdout已经被重定向,可以将消息写到stderr(标准错误输出),stderr不会被重定向。
另外,Linux是一个多用户的系统,我们可以通过利用’/dev/tty‘正确地将信息输出到用户正在使用的终端上。
九、fileno()函数
功 能:把文件流指针转换成文件描述符
相关函数:open, fopen
表头文件:#include <stdio.h>
定义函数:int fileno(FILE *stream)
函数说明:fileno()用来取得参数stream指定的文件流所使用的文件描述词
返回值 :返回和stream文件流对应的文件描述符。如果失败,返回-1。
范例:
- #include <stdio.h>
- main()
- {
- FILE *fp;
- int fd;
- fp = fopen("/etc/passwd", "r");
- fd = fileno(fp);
- printf("fd = %d\n", fd);
- fclose(fp);
- }
文件描述词是Linux编程中的一个术语。当一个文件打开后,系统会分配一部分资源来保存该文件的信息,以后对文件的操作就可以直接引用该部分资源了。文件描述词可以认为是该部分资源的一个索引,在打开文件时返回。在使用fcntl函数对文件的一些属性进行设置时就需要一个文件描述词参数。
以前知道,当程序执行时,就已经有三个文件流打开了,它们分别是标准输入stdin,标准输出stdout和标准错误输出stderr。和流式文件相对应的是,也有三个文件描述符被预先打开,它们分别是0,1,2,代表标准输入、标准输出和标准错误输出。
需要指出的是,上面的流式文件输入、输出和文件描述符的输入输出方式不能混用,否则会造成混乱。
十、fgets会自动将字符串的最后一位置为’\0’
请看一下下面的代码,我们期待输入’12345678’(8个数),用fgets函数输出’12345678’(8个数).
- #include <stdio.h> /*标准输入输出定义*/
- #define PASSWORD_LEN 8
- int main(){
- char password[PASSWORD_LEN+];
- printf("请输入您的密码\n");
- fgets(password,PASSWORD_LEN,stdin);
- printf("您输入的密码是:%s\n",password);
- }
输出结果:
我们可以看出,输出的结果并不是我们所期望的,但是我们也命名在fget里面写了,我们期望的获取8个数(PASSWORD_LEN==8)。原来fget一次调用只能传输n-1个字符,因为它必须把空字节’\0’加上以结束字符串。也就是,如果我们要让输出跟我们的期望相符,那么我们要修改fget函数的参数,如下代码段所示。
- fgets(password,PASSWORD_LEN+,stdin);
十一、malloc函数的学习
- #include <stdlib.h>
- #include <string.h>
- int main(){
- char * s="123.33";
- int i=;
- char **endp= (char **)malloc(sizeof(int)*);//先分配五个整型数据空间,这5个空间就可以用来存储每个二级指针的首地址了。
- for(i=;i<;i++){
- endp[i]=(char *)malloc(sizeof(char)*);//再为每个二级指针分配5个char型数据空间,这样,每个元素也就拥有了各自的家。只是这5个空间是用来存储char型的!!endp[0]5个,endp[1]5个等等
- }
- strcpy(endp[],"");
- for(i=;i<;i++){
- printf("endp[%d] is :%s\t,endp的地址是%d\n",i,*(endp+i),endp+i);//可以看出刚分配完的时候,所有的5个endp一维数组的内容都是空
- }
- for(i=;i<;i++){
- printf("endp[0][%d] is :%c,\tendp[0][%d]的地址是%d\n",i,*((*endp)+i),i,((*endp)+i) );
- }
- }
其实可以用malloc动态分配二维数组空间的。
运行结果:
十二、从一段代码中看printf的执行顺序(编译环境为gcc)
- printf("++a=%d,a++=%d\n",++a,a++);
结果分析:
如果输出++a=1,a++=1,那么说明函数是从左执行到右的;如果++a=2,a++=0,那么说明函数是从右执行到左的。
结果截图:
十三、获取系统当前的时间
首先,让我们先看看两个跟时间有关的类型time_t,tm。
time_t:它是一个大到能容纳以秒计算的日期和时间的整数类型。在32位系统上就是32位的的。
tm结构体被定义为至少包含下表所示的成员。
以下代码段展示的是如何获取当前的时间
- #include <time.h>
- #include <stdio.h>
- #include <stdlib.h>
- int main ( int argc, char *argv[] )
- {
- struct tm *tm_ptr,timestruct;
- time_t the_time;
- char buf[]; //用来保存时间字符串
- char *result; //用来保存不能成功转化的字符串指针
- ( void ) time ( &the_time );
- printf ( "the current time is : %s",ctime ( &the_time ) );//获取当前的时间
- tm_ptr = ×truct;
- result = strptime ( ctime ( &the_time ),"%a %b %d %H:%M:%S %Y", tm_ptr );
- printf ( "strptime gives:\n" );
- printf ( "date: %02d/%02d/%02d\n",
- tm_ptr->tm_year % , tm_ptr->tm_mon+, tm_ptr->tm_mday );
- printf ( "time: %02d:%02d:%02d\n",
- tm_ptr->tm_hour, tm_ptr->tm_min,tm_ptr->tm_sec );
- exit ( EXIT_SUCCESS );
- }
十四、设置文件的访问模式,可以利用fcntl.
十五、利用inline可以解决一些频繁调用的小涵数大量消耗栈空间或是叫栈内存的问题
在c中,为了解决一些频繁调用的小涵数大量消耗栈空间或是叫栈内存的问题,特别的引入了inline修饰符,表示为内联涵数。
可能说到这里,很多人还不明白什么是栈空间,其实栈空间就是指放置程式的局部数据也就是函数内数据的内存空间,在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足所造成的程式出错的问题,涵数的死循环递归调用的最终结果就是导致栈内存空间枯竭。
下面我们来看一个例子
- #include <stdio.h>
- inline char* dbtest ( int a ); //函数原形声明为inline即:内联涵数
- int main()
- {
- int i = ;
- for ( i=;i<=;i )
- {
- printf ( "%d is %s\n",i,dbtest ( i ) );
- }
- return ;
- }
- char* dbtest ( int a ) //这里不用再次inline,当然加上inline也是不会出错的
- {
- return ( a%> ) ?"奇":"偶";
- }
上面的例子就是标准的内联涵数的用法,使用inline修饰带来的好处我们表面看不出来,其实在内部的工作就是在每个for循环的内部任何调用 dbtest(i)的地方都换成了(i%2>0)?"奇":"偶"这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。
说到这里很多人可能会问,既然inline这么好,还不如把所谓的函数都声明成inline,嗯,这个问题是要注意的,inline的使用是有所限制的,inline只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句例如while switch,并且不能内联函数本身不能是直接递归函数(自己内部还调用自己的函数)。
说到这里我们不得不说一下在c语言中广泛被使用的#define语句,是的define的确也能够做到inline的这些工作,但是define是会产生副作用的,尤其是不同类型参数所导致的错误,由此可见inline有更强的约束性和能够让编译器检查出更多错误的特性,在c 中是不推荐使用define的。
参考
一些LinuxC的小知识点(一)的更多相关文章
- 一些LinuxC的小知识点(二)
一.read系统调用 系统调用read的作用是:从与文件描述符filedes相关联的文件里读入nbytes个字节的数据,并把它们放到数据区buf中.它返回实际读入的字节数.这可能会小于请求 ...
- 刚接触Linux,菜鸟必备的小知识点(一)
身为一个将要大四的学生,而且还是学计算机的没有接触过linux简直是羞愧难当.这个假期做了一个软件测试员,必须要熟悉linux的操作,所以对于我这个菜鸟我也就说几点比较重要的小知识点吧. 第一.cd指 ...
- Java学习过程中的总结的小知识点(长期更新)
Java学习过程中的总结的小知识点 (主要是自己不会的知识和容易搞错的东西) 计算某个程序运行的时间 long stime=System.currentTimeMillis(); copy3(file ...
- 【转】HTML5的小知识点小集合
html5的小知识点小集合 html5知识 1. Doctype作用?标准模式与兼容模式各有什么区别? (1).<!DOCTYPE>声明位于位于HTML文档中的第一行,处于<h ...
- AngularJS的小知识点
小知识点:$scope和$rootScope (1)每次使用ngController指令,都会调用控制器的创建函数,创建出一个控制器对象. (2)每次创建一个控制器对象,AngularJS都会创建一个 ...
- js中关于value的一个小知识点(value既是属性也是变量)
今天在学习input的value值时,发现这么一个小知识点,以前理解不太透彻. [1]以下这种情况是常见情况,会弹出“测试内容” <input type="button" v ...
- html5的小知识点小集合
html5的小知识点小集合 html5知识 1. Doctype作用?标准模式与兼容模式各有什么区别? (1).<!DOCTYPE>声明位于位于HTML文档中的第一行,处于< ...
- [BS] 小知识点总结-05
[BS] 小知识点总结-05 1. 不论UIWindow的rootViewController是navC.tabBarC还是VC,也不管modalVC和rootVC中间隔着多少个VC,但是modal出 ...
- 一个关于echo的小知识点
一个关于echo的小知识点 echo一个布尔值时,如果是true,输出1,而如果是false,将什么都不输出! 网上搜的一个解释: 对于数字类型来说,false 确实 是 0, 而对strin ...
随机推荐
- Spring 系列教程之 bean 的加载
Spring 系列教程之 bean 的加载 经过前面的分析,我们终于结束了对 XML 配置文件的解析,接下来将会面临更大的挑战,就是对 bean 加载的探索.bean 加载的功能实现远比 bean 的 ...
- jmeter多用户并发
1.需要参数化 2.单用户需要在请求头里面传入cookie
- CSS-弹性布局-伪类选择器-复杂选择器
1.定位 1.堆叠顺序 一旦将元素变为已定位元素的话,元素们则有可能出现堆叠的效果. 如何改变堆叠顺序? 属性:z-index 取值:无单位的数字,数字越大越靠上. 注意: 1.父子元素间,z-ind ...
- HDU 6185(打表代码
/** @xigua */ #include <cstdio> #include <cmath> #include <iostream> #include < ...
- mysql explain中的type列含义和extra列的含义
很多朋友在用mysql进行调优的时候都肯定会用到explain来看select语句的执行情况,这里简单介绍结果中两个列的含义. 1 type列 官方的说法,说这列表示的是“访问类型”,更通俗一点就是: ...
- Java往hbase写数据
接上篇读HDFS 上面读完了HDFS,当然还有写了. 先上代码: WriteHBase public class WriteHBase { public static void writeHbase( ...
- ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树,倍增lca)
https://nanti.jisuanke.com/t/31462 要求在一个矩形中任意选两个点都有唯一的通路,所以不会建多余的墙. 要求满足上述情况下,建墙的费用最小.理解题意后容易想到首先假设全 ...
- OEM-ODM-OBM
Original Equipment ManufacturerOriginal Design ManufacturerOwn Branding & Manufacturing OEM,即“原始 ...
- exec函数
概念 当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,新程序从main函数开始执行.调用exec并不创建新进程,所以前后的进程ID并未改变.exec只是用磁盘上的一个新程序替换了当前进 ...
- 最全js表单验证
/***************************************************************** 表单校验工具类 (linjq) ***************** ...