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;
[email protected]:~/test/asb# gcc test1.c
[email protected]:~/test/asb# ./a.out
-46
-30
110
[email protected]:~/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、檔案指標
[email protected]:~/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讀取命令列引數中的文字檔案,將它們內容輸出
[email protected]:~/test1 % cc test2.c -o mytest
[email protected]:~/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;
}
也可一次向命令列指定更多文字檔案
[email protected]:~/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函式來讀取
[email protected]:~/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;
}
[email protected]:~/test1 % cc test2.c -o mytest
[email protected]:~/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);
}
[email protected]:~/test1 %
下面的例子展示了從鍵盤輸入文字增加到文字檔案後面,如果輸入%end%表示輸入結束。
[email protected]:~/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;
}
執行結果如下
[email protected]:~/test1 % cc test2.c -o mytest2
[email protected]:~/test1 % ./mytest2 hello.txt
hello.txt內容如下:
你好,各位朋友,很高興認識大家。
Google是一家美國的跨國科技企業,致力於網際網路搜尋、雲端計算、廣告技術等領域,開發並提供大量基於網際網路的產品與服務,其主要利潤來自於AdWords等廣告服務。
[email protected]:~/test1 %
[email protected]:~/test1 % cc test5.c -o mytest5
[email protected]:~/test1 % ./mytest5 hello.txt
請輸入文字:你好 ,今天天氣如何?
請輸入文字:今天天氣不錯!
請輸入文字:謝謝!
請輸入文字:%end%
[email protected]:~/test1 % ./mytest2 hello.txt
hello.txt內容如下:
你好,各位朋友,很高興認識大家。
Google是一家美國的跨國科技企業,致力於網際網路搜尋、雲端計算、廣告技術等領域,開發並提供大量基於網際網路的產品與服務,其主要利潤來自於AdWords等廣告服務。
你好,今天天氣如何?
今天天氣不錯!
謝謝!
[email protected]:~/test1 %