PIXNET Logo登入

Y CP的部落格

跳到主文

歡迎光臨Y CP在痞客邦的小天地

部落格全站分類:不設分類

  • 相簿
  • 部落格
  • 留言
  • 名片
  • 5月 18 週二 201012:09
  • C關鍵字 volatile, restrict

參考出處: volatile  1  2
 
compiler 的最佳化編譯,為了增快程式速度,
有時候會很聰明的將程式碼編譯成和原 code 不同,但意思相同的 object code
如下:
for (int i = 0; i < 10000; i++) {
    a = 5;
   a =  a * i;
}
compiler 可以簡化成下列一條敘述:
a = 5 * 9999;
編譯器最佳化,就讓程式變得更有效率。
 
但是當我們某些程式片段不希望做最佳化的時候呢? 就要使用 volatile 關鍵字
volatile 是 C 的關鍵字,用來修飾資料型態,是告訴 compiler 不要對這一個變數的程式碼區段做最佳化。
通常是用在有 multiple threads without using the lock Statement 的時候,
因為這個變數值有可能常常會被外在 routine 改變(在kernel裡面通常是指 interrupt handler )
舉例來說
Volatile char wait;
void xxx(void){
  wait=1;
  while (wait==0);
  .....
  .....
}
void timer0(void) interrupt 1{
  wait=0;
  .......
}
xxx() 中就是等一個 timer 中斷才會執行底下的工作
如果不寫 Volatile 會被編譯器省略掉,因為 wait=1,來 wait  會等於 0
restrict 是 C 的關鍵字,只能用來修飾 pointer,目的是協助 compiler 做最佳化
是告知 compiler ,這一個 restrict pointer 是唯一指向 data 的 pointer,
意即程式當中不會透過其他變數 ( pointer,或者直接存取 ) 來 access 此 data,
例子如下:
int * restrict rptr = (int*) malloc(10*sizeof(int));
int a[10];
int * ptr;
ptr = a;
for(int i =0; i<10;i++) { 
    ptr += 5;
    rptr +=5;
    a *= 5;
    ptr += 3;
    rptr += 3;
}
當 compiler 看到 rptr 為 restric,就會用 rptr += 8 取代 rptr += 3 和 rptr += 5
而 ptr 就不應該被直接替換,因為它不是唯一會 access 該 data 的變數
 
C99 用到restrict的例子:
void* memcpy (void* restrict destination, const void* restrict source, size_t n);
代表destination和source區段是不可重疊的
 
FILE *fopen(const char *restrict pathname, const char *restrict type);
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(10,542)

  • 個人分類:電腦和網際網路
▲top
  • 4月 09 週五 201011:19
  • 函數呼叫

函數呼叫 (Function Call)        參考1  參考2      
以硬體的觀念來講,函數是放在記憶體中的一群指令,而每個函數被放置在不同的記憶體,如下圖所示:
 ┌──────────────────────────┐
 │  ┌───────────────────────┐  │
 │  │IP↘                                                                 code (text)   │  │
 │  │     ┌───┐      ┌────┐    ┌────┐      │  │
 │  │     │main(  )│      │函數 A( )│    │函數 B(  )│      │  │
 │  │     └───┘      └────┘    └────┘         │  │
 │  └───────────────────────┘  │
 │        ┌──────┐┌───┐┌────────┐    │
 │        │   data heap   ││ stack    ││ global name space  │    │
 │        └──────┘└───┘└────────┘    │
 └──────────────────────────┘
   code:放置程式碼的區塊,也叫做 text,意即程式的本文之意。
   data heap:所有的區域變數都被放在這裡。
   stack:此塊記憶體是給編譯程式和作業系統應用的,我們通常無法直接取用。
   global name space:放置所有的靜態變數、全域變數以及外部變數。(在 UNIX 系統下這塊記憶體也叫做 bss)
一個程式佔據多大的記憶體,在 UNIX 系統下可以用 size 這個指令看出來,例如我們想看看 gcc 佔了多大的記憶體空間:
  [thccy14]/usr/local/bin> size gcc
  text    data    bss     dec     hex     filename
  57312   8192    0       65504   ffe0    gcc
 可以看到 gcc 的 code 有 57312 bytes,需要 8192 bytes 的 data heap,不需要 bss。
程式的執行過程:
首先,有一個叫做IP(Instruction Pointer,CPU 會依序執行IP所指位址的指令)的暫存器會指向程式開始的地方
(通常是 main 函數),當函數呼叫發生時,硬體按照下列的流程執行程式的控制權轉移:
                           函數呼叫發生
                                ↓
                 把目前的程式執行狀態存進 stack (含 IP) ,把函數的參數由右而左存進 stack
                                            ↓
                     把 IP 指向欲前往的函數
                                ↓
                            前往函數
進入函數之後,函數由 stack 取得參數 (這部份的碼由編譯器自動產生)之後,開始執行,執行完畢時依以下的流程交回控制權:
                              函數結束
                                 ↓
                        將傳回值存入 stack
                                 ↓
                   取出 stack 中原程式執行狀態,恢復原程式執行狀態
                                          ↓
                        取出傳回值,儲存目前的IP
                                          ↓
                      繼續執行原來的程式
每呼叫一次函數, CPU 就必須浪費很多時間來處理這些記憶體的儲存和更新,會使執行的速度變慢,
所以說遞迴函數不斷地執行函數的呼叫,因此會使執行速度較慢。
一個 activation record (stack frame) 儲存程式的:
–參數與本地變數
–執行結果(回傳值)
–返回位址(return address)
–其他環境資訊(詳見第6單元)
當一個程式被呼叫執行時,系統會自動配置一個activation record (stack frame)給它儲存以上資訊,
並且push這些資訊到stack;副程式執行結束時,便從其activation record中取得返回位址,回到上一層
(當初呼叫它的)程式繼續執行下一句,而系統也在此時收回它的 A.V。
同一支執行中程式的所有副程式的 A.V,都是放在同一個 stack 上,先進後出。
有些書把這個 stack 叫做 system stack (系統堆疊)。
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(3,053)

  • 個人分類:電腦和網際網路
▲top
  • 3月 29 週一 201018:20
  • C vs C++

 
C vs C++
STL
OOP
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(45)

  • 個人分類:電腦和網際網路
▲top
  • 3月 20 週六 201000:17
  • Pointer to function

前天跟張貿翔老師的計概課
 
Pointer to void   可存任意型態的指標
使用: void* p; //
    double i;
    p = &i;
Pointer to function    指標指向一段程式的起始位置
使用:
 double (*f) (float); // 指標 f 指向某個function,其傳入參數型態為 float,回傳型態為 double
 f = X; // f 指向function X,X意即代表X這個函式的起始位置
 result = (*f)( v1 ); // result 型態要double,v1 要float
 
C語言編譯器的程式庫參考手冊, 有一組與 ANSI C 相容的函數 qsort, bsearch
規格說明:
 void qsort(void *base, sizt_t nelem, size_t width, 
     int (*fcmp)(const void *, const void *));
 void bsearch(const void *key, const void *base, size_t nelem, size_t width,
    int (*fcmp)(const void *, const void *));
 以上 #include <stdlib.h> 則可使用 
qsort (待排序 data 的起始位置, data的個數, data的大小,單位byte, 一個做比較大小的函式)
其中
 int (*fcmp)(const void *, const void *))  代表會呼叫一個使用者自製的函式
 如果今天要使用 qsort 排序 int,則我們製作的是一個可以比較兩個int參數大小的 function
 像這樣: int ComInt( const int *x, const int *y ){ statement }
然而
 如果今天要使用 qsort 排序 string,那我們要製作的就是根據我們自己定義(怎樣是大? 怎樣是小?)比較大小的 function
所以這就是 function pointer 的一個優點:
在製作一個可以比較廣泛使用(如上可以排序各種型態)的函式時,幫助使其簡化(只針對參數稍微調整程式)。
 
另外,在 int (*fcmp)(const void *, const void *)) 中傳入的參數是指標型態,而不是只傳 value,(只是做比較又沒有要改值,可以傳 value 就好阿?)
這是由於在比較大小時,當我們比較的不是 float, char 等基本數型,而是字串(即字元陣列)時,qsort 才能夠正確的運作。
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(736)

  • 個人分類:電腦和網際網路
▲top
  • 3月 07 週日 201010:24
  • 陣列的參數傳遞

reference
C語言只能傳遞指標,無法傳遞陣列的內容。
假設要傳遞一個二維陣列,則C會幫我們將該陣列的起始位置傳入。
參數宣告部分  有如下不同的方式:
錯誤示範
 void foo1(int x[][]) {  // 編譯過,但Compiler不知如何翻譯
      x[2][2] = 0;  // 編譯錯誤,Compiler不知如何翻譯
 }
 void foo4(int x[3][]) {  // 編譯錯誤。
 }
 
無論是幾維的陣列,C語言都是分配一塊連續的記憶體空間來處理。
於是其是以row major的方式來處理多維到一維的對應。
因此副程式的陣列參數宣告應該給予column大小(二維)
正確示範
 void foo2(int x[][3]) {  // Compiler知道如何翻譯
      x[1][1] = 0;  // Compiler知道要翻成*(x+1*3+1)
 }
 void foo3(int x[2][3]) {  // Compiler知道如何翻譯
      x[1][1] = 0;  // Compiler知道要翻成*(x+1*3+1)
 }
 void foo5(int *x) {  // 能傳入pointer,也能傳一個陣列起始位置*M(int M[o][x]),
           但是副程式內部的位址要自己計算,因為Compiler不知道你的column大小
      *(x+1*3+1) = 0;  //位址要自己計算   *(M+1*x+o)
 }
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(1,534)

  • 個人分類:電腦和網際網路
▲top
  • 2月 21 週日 201023:58
  • memcpy動態陣列

memcpy
 作用: Copy block of memory
 用法:memcpy(指向destination的指標, 指向source的指標, 要copy幾個byte)
 see here
new
 作用:C++動態配置記憶體
 介紹:依所指定之型別與陣列大小配置一塊等大的記憶體
    可以為其設定初值
    return 該塊記憶體的起始位址
    通常需要一指標來接收回傳值,以存取所配置的記憶體空間
 格式:
  變數型別* 指標 = new 變數型別;  //不指定初值
  變數型別* 指標 = new 變數型別(初始值);  //指定初值
 
  變數型別 *指標名 = new 變數型別[陣列長度];  //一維陣列
  //多維陣列
  變數型別 (*指標名)[陣列長度2] = new 變數型別[陣列長度1] [陣列長度2];
  變數型別 (*指標名)[陣列長度2] [陣列長度3]= new 變數型別[陣列長度1][陣列長度2] [陣列長度3];
  ex: int *p3 = new int[10];
    double (*p4)[4] = new double[3][4];
    double (*p5)[4][5] = new double[3][4][5];
 
因為memcpy只能複製連續記憶體,所以要自製具有連續記憶體的動態陣列 see here
template < typename T >
T **Allocate2DArray( int nRows, int nCols){
    T **pp;
    T *p;
    T *curPtr;
    //(step 1) 宣告一個指標陣列的空間,內容指向元素陣列 each row 的開頭。pp指向指標陣列的起始位置。
    pp = new T*[nRows];
    //(step 2) 宣告一個元素陣列的空間。p指向元素陣列起始位置。
    p = new T [nRows * nCols];
    //(step 3) 將指標陣列裡的指標,指向元素陣列的正確位置。
    curPtr = p;
    for( int i = 0; i < nRows; i++){
        *(pp + i) = curPtr;
         curPtr += nCols;
    }
    return pp;
}
template < typename T >
void Free2DArray(T** Array){
    delete [] *Array;
    delete [] Array;
}
 
使用
 型態  **變數名稱 = Allocate2DArray<型態> ( 行數, 列數 )
  例:double **A = Allocate2DArray<double> ( 5, 7 );   //宣告5列7行的 double 二維陣列
 Free2DArray ( 變數名稱 ) 
  例:Free2DArray(A);
 可以像一般陣列一樣assign值
  例:A[2][5] = 0.5
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(2,551)

  • 個人分類:電腦和網際網路
▲top
  • 2月 11 週四 201014:49
  • function template

Function template  為「通用函式」(Generic function),和一般 function 不同的地方在於,可以為不同type的資料做相同的動作。也就是,將type給參數化,等到呼叫時才決定給的是什麼type。
定義Template
 template <typename T>  
 T GetMin (T a, U b) { 
      return (a<b?  a : b);
 }
 //或者寫成template <class T> T是自己取的參數名稱
 //可傳入兩個不同type的參數,在這個例子裡,這兩種是可以比大小的
使用
 遇到的問題
 function template 只拿回傳 type 當參數時,要明確指定它的 type
 template <class T> T** G(int M, int N) {
     T **ppi;
     /*      */
     return ppi;
 }
 int main(int argc, char *argv[]){
     double **d = G<double>(5,3); <=明確指定double
 }
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(26)

  • 個人分類:電腦和網際網路
▲top
  • 2月 01 週一 201014:03
  • 專案設定(using Matlab)

新增環境變數
=>使用者變數 
名稱MATLAB , 路徑C:\Program Files\MATLAB71
 
專案
專案=>屬性=>組態屬性=>C/C++ =>一般=>include C:\Program Files\MATLAB71\extern\include;C:\Program Files\MATLAB71\simulink\include
專案=>屬性=>組態屬性=>連結器=>命令列=>其他選項 libeng.lib libmat.lib libmx.lib libmex.lib
工具=>選項=>VC++目錄=>程式庫檔  $(MATLAB)\extern\lib,   $(MATLAB)\extern\lib\win32\microsoft
 
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(559)

  • 個人分類:電腦和網際網路
▲top
  • 1月 29 週五 201012:58
  • 連續讀檔

#include <windows.h> 
#include <tchar.h>   
 
int main(int argc, char *argv[]){
    WIN32_FIND_DATA FileData;
    BOOL fFinished;
    HANDLE hList;
    FILE *stream;
   
    hList = FindFirstFile("*", &FileData);
    if (hList == INVALID_HANDLE_VALUE){
        printf("No files under this direction");
    }
    else{
              fFinished = FALSE;
               while (!fFinished){
                         if ( strstr(FileData.cFileName,".txt") ){ //判斷副檔名是不是 .txt  
                                  stream = fopen(FileData.cFileName,"r"); //fopen( const char * filename, const char * mode );
                                  if(stream==NULL){
                                            //return;
                                  }
                                  else{ //讀檔                    
                                  }
                                  fclose(stream); 
                           }//if 判斷副檔名是不是 .txt
                          //--------------計算-------------//
                           if (!FindNextFile(hList, &FileData)){
                                   if (GetLastError() == ERROR_NO_MORE_FILES){
                                           fFinished = TRUE;
                                   }
                            }
                 }//while
    }
    FindClose(hList);
    system("PAUSE");
    return EXIT_SUCCESS;
}
 
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(376)

  • 個人分類:電腦和網際網路
▲top
  • 1月 28 週四 201013:04
  • vc++ 2008 / 2005

Breaking Changes (CRT)   中文   reference1  2
 
fopen => fopen_s
FILE*  fopen ( const char * filename,  const char * mode );.
errno_t  fopen_s( FILE** pFile,  const char *filename,  const char *mode );
 
stream = fopen(FileData.cFileName,"r");                   
if(stream==NULL){
        printf("cannot open file\n");
        exit(
0);
}
------------------------------------------------
if( fopen_s( &stream, FileData.cFileName, "r" ) !=0 )
    printf(
"The file 'crt_fopen_s.c' was not opened\n" );
    exit(0);

}
 
(繼續閱讀...)
文章標籤

Y CP 發表在 痞客邦 留言(0) 人氣(18)

  • 個人分類:電腦和網際網路
▲top
12»

自訂側欄

自訂側欄

個人資訊

Y CP
暱稱:
Y CP
分類:
不設分類
好友:
累積中
地區:

熱門文章

  • (10,542)C關鍵字 volatile, restrict
  • (3,053)函數呼叫
  • (2,551)memcpy動態陣列
  • (376)連續讀檔
  • (96)如此濃烈的「色」,如此肅殺的「戒」 - 龍應台
  • (41)令人高興的心理測驗

文章分類

  • 娛樂 (2)
  • 植物 (3)
  • photoshop (4)
  • 自然科學 (1)
  • 電腦和網際網路 (12)
  • 未分類文章 (1)

最新文章

  • 圖片格式 gif, jpg, png
  • C關鍵字 volatile, restrict
  • 夕陽的顏色
  • 自動裁剪 掃描相片
  • 快樂數
  • 函數呼叫
  • C vs C++
  • Pointer to function
  • 陣列的參數傳遞
  • photoshop 工作環境

最新留言

  • [24/03/30] 新飛Hsinfei 於文章「主題論述:為甚麼我們應該把我們的病歷中文...」留言:
    醫護英文對話10句分享,不需靠醫護英文翻譯軟體也能溝通! h...
  • [19/11/15] 廣利 於文章「難過..是一種病...」留言:
    超級生命密碼-泯恩仇,導師演唱版 連結網址: https...
  • [15/01/23] miller 於文章「主題論述:為甚麼我們應該把我們的病歷中文...」留言:
    邏輯錯亂。我只提出幾點: >難道大家這麼多的病歷每份真...
  • [09/09/16] Cindy 於文章「開學...」留言:
    真的!!!!!!! 在北京生活的這麼幾個月 我深深的認知一件...
  • [08/10/21] ... 於文章「林呆呆要見丈人&丈母娘...」留言:
    Go Go Go A Le A Le A Le!!! ...
  • [08/10/19] takeeasy 於文章「林呆呆要見丈人&丈母娘...」留言:
    囧囧囧 ...
  • [07/09/13] 政維 於文章「winter in July...」留言:
    寫的真好  我喜歡 ...
  • [07/09/12] CP 於文章「winter in July...」留言:
      Future dreams can never las...
  • [07/08/31] frank 於文章「新的耳環!...」留言:
    正喔~  ...
  • [07/08/30] CP 於文章「none...」留言:
    小雞真貼心  親一個   ~~*  ...

動態訂閱

文章精選

文章搜尋

誰來我家

參觀人氣

  • 本日人氣:
  • 累積人氣: