C指针原理(24)-C指针基础
取自netbsd中的源码,检查运算溢出,用C语言实现,方法很精妙
/*
hide bintime for _STANDALONE because this header is used for hpcboot.exe,
which is built with compilers which don't recognize LL suffix.
* http://mail-index.NetBSD.org/tech-userlevel/2008/02/27/msg000181.html
*/
下面这段使用了LL后缀,要检查一下编译器是否支持,如果支持,则定义_STANDALONE。这样能容纳的时间数更大。
L是long,LL是long long
定义了bintime的结构,以及其加减运算。uint64_t类型的frac是无符号整数,下面要用到这个特性
#if !defined(_STANDALONE) struct bintime { time_t sec; uint64_t frac; }; static __inline void bintime_addx(struct bintime *bt, uint64_t x) { uint64_t u; u = bt->frac; bt->frac += x; if (u > bt->frac) bt->sec++; }
数据是以补码方式存放在内存中!无符号整数溢出表现为: x + y < x 就表示溢出了.,因此,上面才有
if (u > bt->frac)
bt->sec++;
这样的判断,很巧妙的想法,溢出了就进位。
下面演示了加法的溢出
因为上面编译器进行编译时,char是有符号的,即signed char。
在C/C++语言中,char变量为一个字节,8位,signed char表示的范围:-128~127【-128在内存中的二进制表示为1000 0000,127在内存中的表示为0111 1111】;unsign char表示的范围:0000 0000~1111 1111,即0~255;
root@myhaspl:~/test/asb# gcc test1.c
root@myhaspl:~/test/asb# ./a.out
-46
-30
110
root@myhaspl:~/test/asb#
很明显,90+120已经溢出了,因为无法表达210这个有符号数,用一个8位的字节。而a+c则正常计算。
下面继续分析。
static __inline void bintime_add(struct bintime *bt, const struct bintime *bt2) { uint64_t u; u = bt->frac; bt->frac += bt2->frac; if (u > bt->frac) bt->sec++; bt->sec += bt2->sec; }
bintime_add也完成2个时间结构类型的加法,同样通过溢出检查来实现进位。
下面是2个时间结构类型的减法。
static __inline void bintime_sub(struct bintime *bt, const struct bintime *bt2) { uint64_t u; u = bt->frac; bt->frac -= bt2->frac; if (u < bt->frac) bt->sec--; bt->sec -= bt2->sec; }
9、文件指针
dp@dp:~/test1 % vim test2.c #include <stdio.h> #include <stdlib.h> int main(int argc,char **argv){ int exit_status=EXIT_SUCCESS; while (*++argv!=NULL) { //打开文件,如果出现错误,则显示错误信息 FILE *input=fopen(*argv,"r"); if (input==NULL){ perror(*argv); exit_status=EXIT_FAILURE; continue; } printf ("\n%s内容如下:\n",*argv); int ch; while((ch=fgetc(input))!=EOF){ printf("%c",ch); } if (fclose(input)!=0){ perror(*argv); exit_status=EXIT_FAILURE; } } return exit_status; }
上面程序使用fgetc读取命令行参数中的文本文件,将它们内容输出
dp@dp:~/test1 % cc test2.c -o mytest
dp@dp:~/test1 % ./mytest test1.c
test1.c内容如下:
#include <stdio.h> int add(int a,int b); int main(void){ int (*myfunc)(int a,int b); myfunc=add; int x=myfunc(12,36); printf("%d",x); return 1; } int add(int a,int b){ return a+b; }
也可一次向命令行指定更多文本文件
dp@dp:~/test1 % ./mytest test1.c test3.c hello.txt #include <stdio.h> int add(int a,int b); int main(void){ int (*myfunc)(int a,int b); myfunc=add; int x=myfunc(12,36); printf("%d",x); return 1; } int add(int a,int b){ return a+b; }
test3.c内容如下:
#include <stdio.h> int main(int argc,int **argv){ printf ("%s","abcdefgh"+2); } hello.txt内容如下: 你好,各位朋友,很高兴认识大家。
Google是一家美国的跨国科技企业,致力于互联网搜索、云计算、广告技术等领域,开发并提供大量基于互联网的产品与服务,其主要利润来自于AdWords等广告服务。
也可以使用fgets函数来读取
dp@dp:~/test1 % vim test2.c #include <stdio.h> #include <stdlib.h> int main(int argc,char **argv){ int exit_status=EXIT_SUCCESS; while (*++argv!=NULL) { //打开文件,如果出现错误,则显示错误信息 FILE *input=fopen(*argv,"r"); if (input==NULL){ perror(*argv); exit_status=EXIT_FAILURE; continue; } printf ("\n%s内容如下:\n",*argv); char mytext[500]; while(fgets(mytext,500,input)!=NULL){ printf("%s",mytext); } if (fclose(input)!=0){ perror(*argv); exit_status=EXIT_FAILURE; } } return exit_status; } dp@dp:~/test1 % cc test2.c -o mytest
dp@dp:~/test1 % ./mytest hello.txt test3.c
hello.txt内容如下:
你好,各位朋友,很高兴认识大家。
Google是一家美国的跨国科技企业,致力于互联网搜索、云计算、广告技术等领域,开发并提供大量基于互联网的产品与服务,其主要利润来自于AdWords等广告服务。
test3.c内容如下:
#include <stdio.h> int main(int argc,int **argv){ printf ("%s","abcdefgh"+2); }
dp@dp:~/test1 %
下面的例子展示了从键盘输入文字增加到文本文件后面,如果输入%end%表示输入结束。
dp@dp:~/test1 % vim test5.c #include <string.h> #include <stdio.h> #include <stdlib.h> int main(int argc,char **argv){ int exit_status=EXIT_SUCCESS; while (*++argv!=NULL) { //打开文件,如果出现错误,则显示错误信息 FILE *output=fopen(*argv,"a"); if (output==NULL){ perror(*argv); exit_status=EXIT_FAILURE; continue; } char mytext[500]; int ch='\n'; while (1){ printf("请输入文字:"); scanf("%s",&mytext); if (strcmp(mytext,"%end%")!=0){ fputs(mytext,output); //scanf函数不会读取换行符,因此加上换行符 fputc(ch,output); } else break; } if (fclose(output)!=0){ perror(*argv); exit_status=EXIT_FAILURE; } } return exit_status; }
执行结果如下
dp@dp:~/test1 % cc test2.c -o mytest2
dp@dp:~/test1 % ./mytest2 hello.txt
hello.txt内容如下:
你好,各位朋友,很高兴认识大家。
Google是一家美国的跨国科技企业,致力于互联网搜索、云计算、广告技术等领域,开发并提供大量基于互联网的产品与服务,其主要利润来自于AdWords等广告服务。
dp@dp:~/test1 %
dp@dp:~/test1 % cc test5.c -o mytest5
dp@dp:~/test1 % ./mytest5 hello.txt
请输入文字:你好 ,今天天气如何?
请输入文字:今天天气不错!
请输入文字:谢谢!
请输入文字:%end%
dp@dp:~/test1 % ./mytest2 hello.txt
hello.txt内容如下:
你好,各位朋友,很高兴认识大家。
Google是一家美国的跨国科技企业,致力于互联网搜索、云计算、广告技术等领域,开发并提供大量基于互联网的产品与服务,其主要利润来自于AdWords等广告服务。
你好,今天天气如何?
今天天气不错!
谢谢!
dp@dp:~/test1 %
- C指针原理(15)-C指针基础
- C指针原理(16)-C指针基础
- C指针原理(19)-C指针基础
- 新ccna基础--24 路由原理和静态路由
- 算法24:智能指针的原理和使用
- C指针原理 (26)-C指针基础
- C指针原理(17)-C指针基础
- C指针原理(24)-const类型
- C指针原理(17)-C指针基础
- C指针原理(21)-C指针基础
- C指针原理 (25)-C指针基础
- C指针原理(33)-C指针基础
- C指针原理(96)-C基础综合应用
- C指针原理(21)-C指针基础-AT&T汇编
- C++基础7【难】 多态:实现原理 vptr指针 证明vptr存在 类的步长 纯虚函数:抽象类 案例 【面试题】
- C指针原理(14)-C指针基础
- C指针原理(13)-C指针基础
- C指针原理(12)-C指针基础
- C指针原理(18)-C指针基础
- JAVA基础之理解JNI原理