一些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 ...
随机推荐
- Collection和Collections的区别是什么
1)java.util.Collection是一个集合顶层接口,该接口的设计目的是为各种具体的集合提供最大化的统一的操作方式,它提供了对集合对象进行基本操作的通用接口方法,实现该接口的类主要有List ...
- Laravel Relationship Events
Laravel Relationship Events is a package by Viacheslav Ostrovskiy that adds extra model relationship ...
- [Office]Execl取消保护密码
2007版Excel表格中可以按照以下方式建宏: 打开Excel表格中的Excel选项,选择自定义,得到如下画面: 然后在左边侧框栏中选择“查看宏”或者Alt+F11 之后双击或者选择添加按钮,则可 ...
- H3 android 系统编译
http://bbs.ickey.cn/group-topic-id-57981.html [Orange Pi PC试用体验]11编译android源码笔记 编译android和编译linux有点类 ...
- codeforces C. Functions again
题意:给定了一个公式,让你找到一对(l,r),求解出公式给定的F值. 当时没有想到,我把(-1)^(i-l)看成(-1)^i,然后思路就完全错了.其实这道题是个简单的dp+最长连续子序列. O(n)求 ...
- IDEA的GUI连接数据库写入SQL语句的问题总结
一.首先是建立游标的对象statement 插入数据excuteUpdate需要的是一个整型的参数,所以建立的对象要是一个int型的数据类型,才可以执行SQL语句excuteQuery是一个字符类型在 ...
- 10个相见恨晚的 Java 在线练手项目
10个有意思的Java练手项目: 1.Java 开发简单的计算器 难度为一般,适合具有 Java 基础和 Swing 组件编程知识的用户学习 2.制作一个自己的 Java 编辑器 难度中等,适合 Ja ...
- 菜品识别 API调用
#get_access_token.py #获取access_token 1 import requests def GetToken(API_KEY,SECRET_KEY): url = 'http ...
- Android APP测试流程
一. Monkey测试(冒烟测试) 使用monkey测试工具进行如下操作: 1. APP的安装 2. APP随机操作测试(APP压力测试) 3. APP的卸载 二. 安装卸载测试 1. 使用测试真机进 ...
- CloneZilla 恢复系统报错Waiting for device dev/disk/by-id/.....
利用CloneZilla备份好系统,在恢复系统时候显示恢复成功,但在重启系统时出现如下错误: 出现问题的原因: 原因在于suse系统的一个新的默认设置,这个新的默认设置为存储设备由原来的名称相关改为I ...