Posts

Showing posts with the label C language

[c] const的使用

在 effective C++ 一書中有提到: use const whenever possible. 今天又遇到了, 來複習一下.   char myStr[] = "Hello";        non-const ptr / non-const data   const char* pStr = myStr;     non-const ptr / const data   char* const pStr = myStr;            const ptr / non-const data   const char* const pStr = myStr;   const ptr / const data 我的理解是:const 是修飾詞,   const char* pStr  =>  pStr 為一個 pointer, 存的變數型態是 char*, 該變數為const.   char* const pStr = > pStr 為一個 const 的 pointer, 存的變數型態為 char*   const char* const pStr =>  pStr 為一個 const 的 pointer, 存的變數型態為 char*, 該變數為const. 另外 const Object * var 等同於 Object const* var.

[讀書心得] ffmpeg tutorial (三) Playing sound

這集主要是介紹透過 SDL 播放 sound. Audio -   (1) 由一連串 streams 所組成, 每個 stream 又稱為一個 sample, 表示 audio waveform.   (2) 如何撥放 audio 是由 sampling rate 決定, 表示每秒播放 N samples. Ex. 22050 for radio, 44100 for CD.   (3) multichannels for stereo or surround   (4) 當我們得到 video 的部份 data 時, 會得到一個完整的 samples. 也就是說: 我們無法預期得到的 sample 數, 但 ffmpeg 也不會將 samples 分成數段. SDL 播放 audio 的做法為:   10 Audio information Setup, including sampling rate (named frequency in SDL), number of channels, callback function, userdata, etc.   20 Call callback function and fill audio data into SDL_AduioSpecs.   30 Call SDL_OpenAudio()   40 Back 20 until finished

[讀書心得] ffmpeg tutorial (二) Drawing images to screen

這集介紹透過 ffmpeg 將 stream 轉為 Images 輸出, 採用的是 SDL (Simple Direct Layer).   SDL 的簡單說明:      (1) Simple DirectMedia Layer      (2) written by c, but C++ compatible.      (3) cross-platform (Linux, Windows, Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, OpenBSD, BSD/OS, Solaris and QNX)      (4) low level access to hardware device, ex. keyboard, audio, mose, joystick, 3D hardware(via OpenGL), 2D video framebuffer.      (5) GNU LGPL v2 (表示只要透過dynamic library, 即可作為商業用途; 只有再修改SDL源碼才要公布修改的部分跟使用的代碼)      (6) Language biding (ex. C#, Java, Lisp, Lua, Object-C, PHP, Python, Ruby and smalltalk)      (7) DirectX之於Windows, 等同SDL之於nonWindows      (8) Current Version 1.2.15 (Jan. 20, 2012) resource click here . SDL 對於呈現 image 很多方法, 這裡介紹一種 YUV overlay.(這以前在學校有接觸過, 可當時根本不知道在幹嘛... ) YUV(technically, YCbrCr) 是一種儲存 raw image 的格式, 其他的格式像是 RGB. Y: brightness/luma component, U and...

[讀書心得] ffmpeg tutorial (一) Making Screencaps

Media files 種類分成 music, image, video. 每個 file 自身又稱為 container , 各自的格式如下:   -music container : AIFF(mac), WAV(windows), XMF(extensible music format), etc.   -image container : TIFF, FITS, etc.   -video container : 3GP, AVI, ASF, Matroska, Quick Time, MPEG, MP4, RM, etc. container type 決定了 儲存於 file 的資訊(這不廢話...) container 由 streams  (audio/video) 所構成, 每個 stream又可以分成數個 frames . 其中 streams 被各種 codec 以 encode 方式儲存於 container.  codec 定義了 stream 如何被 enCOde 跟 DECode, 如 H.264, Xvid, MP3.  不過在傳送時,  streams 是以數個 decoded 的 raw frames 為單位, 稱作 packet. 一個簡單的處理程序如下: 10 OPEN video_stream FROM video.avi 20 READ packet FROM video_stream INTO frame 30 IF frame NOT COMPLETE GOTO 20 40 DO SOMETHING WITH frame 50 GOTO 20 不過這裡有幾個疑問(Q1):     (1) packet 是固定大小的 frames?      (2) 一個 image 由固定大小的 frames 組成? audio 又是怎麼傳輸?          恩, 直覺上最簡單的做法是每次收 data frames 時先檢查大小.    ...

[C] 關於static variable的宣告

static variable跟一般variable的宣告方式, 差別是在程式執行開始到結束之前都存在記憶體中. (1)當static variable為Local variable時: void myFunc(int n) { static int num = 0; num += n; } => num在宣告為static後, 儘管離開myFunc()後仍會一直存在, 而且每次執行myFunc會進行num的累加(而不是從0開始) (2)當static variable為global variable時: 當在a.c中宣告 static int num = 0後, num只能被a.c這個檔案所引用, 而不能被其他.c或.h檔使用(即無法在其他檔案中宣告extern int num;) (NOTE)若在.h檔中宣告int num; 表示每個引用的.c檔會發生錯誤(multiple definition). 若宣告為static int num; 則每個引用的.c檔都會copy一份num變數. 建議最好不要在.h檔中宣告變數, 若需要不同.c檔共用同一個變數, 可以使用: (a)在某個.c檔裡頭宣告, 然後在其.h檔宣告extern. 需要引用該變數的.c檔則將該.h加入 (b)使用function call的方式取得 若每個.c都需要有各自的int num, 則各自宣告為static int num. 恩, 目前理解是如此, 有問題再來修改...

[c] 涵式的指標參數

平常寫一個指標參數都很直覺得寫, 今天想到一個有趣的記法, 在這裡筆記一下.. 最基本的是我們要傳 reference of variable時: 1: int a; 2: rewrite(&a); 3: void rewrite(int *a); 若忘記參數要怎宣告, 想到一個很有趣的記法就是, 由右往左推: a. 在2時傳入a的位址, 勢必以 *a型態記錄 b. 而參考1, a是type int, 所以宣告 int. => "int *a" ex. 1: char *str=NULL; 2: rename(&str); 3: void rename(char **str2); str是個pointer, 存一個type char的address 在rename()中傳入一個address -> *str 又str是一個char * -> char**str &str == str2 *str2 = (char*)malloc(...)

[C]關於 ioctl 跟 ifreq

ioctl() 是提供對device作input/output control的system call, 根據deivce的不同所實作的參數也不同, 但前兩個是固定的. <code>int ioctl(int d, int request, ...)</code> 主要有3個參數: 1. d: descriptor, 是透過open()某個device而得到的handle(linux稱descriptor而windows稱handle), 主要是描述該deivice的abstract indicator. 2. request: 根據不同的device提供的request也不同 ex. SIOCGIFADDRS - Gets the list of addresses associated with an interface. SIOCGIFADDR  - gets an interface address 取得本機位址  int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);  struct ifreq ifr;  ifr.ifr_addr.sa_family = AF_INET;  strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);  ioctl(sock_fd, SIOCGIFADDRS, &ifr); 另外就是 ifreq 是指用來config network device的結構 struct ifreq {     char    ifr_name[IFNAMSIZ];/* Interface name */     union {             struct sockaddrifr_addr;             struct sockaddrifr_dst...

[C] 一些data type

今天在看一個源碼時對一個 data type "uintptr_t" 不了解, google之後發現原來他是有作用的, 來筆記一下. 從 linux man page 可以知道他的宣告是 typedef unsigned int unit16_t; typedef uint16_t uintptr_t; 源自 主要作用是為了再跨平台時, 程式碼可以保存不受破壞. 以下是在x86 debian下跑的結果 printf("signed char:%d\n", sizeof(signed char)); printf("signed short:%d\n", sizeof(unsigned short)); printf("signed int:%d\n", sizeof(signed int)); printf("size_t:%d\n", sizeof(size_t)); printf("signed long:%d\n", sizeof(signed long)); printf("signed long long int:%d\n", sizeof(signed long long int)); debian:/home/xxx/shares/C# ./test_datatype signed char:1 signed short:2 signed int:4 size_t:4 signed long:4 signed long long int:8 另外是一個很神(或說機車)的寫法... [Symbol.h] extern char *symbol_values[]; #define SYMBOL_NAME_ENUM(name) symbol_##name #define SYMBOL(name) symbol_values[SYMBOL_NAME_ENUM(name)] ... ... #define SYMBOLS_DO(action) \ /* Method and field names, etc. */\ action(f, "f"), \ action(m, "m...

[C] 關於pointer與型態宣告

複習一下pointer... (1)pointer: 指標, 用來儲存 資料物件 的記憶體位址. ex. int var    = 8; int *ptr   = &var; //儲存var位址的指標變數ptr(或說是指向變數var的指標ptr), 其var 為int type int **pptr = &ptr;   <=> int* (*pptr) = &ptr; //儲存ptr位址的指標變數pptr, 其中ptr為int* type (2)*VARIABLE_NAME 可以取出所指向的位址物件的數值. ex. printf("   *ptr=%d\n", *ptr); // 8 printf(" *pptr=%u\n", *pptr); // memory address of var NOTICE 1: *pptr得到的是所存位址(即ptr的位址)的數值(ptr存的是var的位址) NOTICE 2: 不管宣告時有幾個'*', 指標變數,存的就是資料物件的位址. printf("**pptr=%d\n", **pptr); //8 另外就是宣告的型態: (I)   int arr[8][8];  //int array的 array (II)  int **pptr;    //指向int type pointer的 pointer (III) int *parr[8]; //8個指向 int type pointer的 array (IV) int (*parr)[8]; //指向int array的 pointer (V)  int *parr2[7][8]; //指向int type pointer的7x8 array (VI) int (*parr2)[7][8]; //指向7x8array的 pointer (VII)int (*parr2[7])[8]; //7個指向int type array的 array int *parr[7][8];  表示parr是一個有7個elements的array, 每...

[C] numerical operation

最近閒著,來複習一下數值運算... Binary representation: 1 byte = 8 bits 可以表示 0~255 或 -128~127, 至於程式表示負數的方式, 是由硬體決定。 一般表示方式為: a.用最高位的那個bit(the most significant bit, MSB)表示正負數 b.當MSB=0, 表示0~127, 當MSB=1, 則以2's complement看之. ex. 00000011=3 10000001=01111111=-127 (作法: 從LSB開始, 第一個為1的bit不動,其餘的0->1, 1->0) 10000000=10000000=-128 11111111=00000001= -1 Binary Logical Operator: '~': 。補數運算子 。ex. ~(1001101) -> 0110010 '&': 。ex. 10010011 & 00111101->00010001 '|': 。ex. 10010011 | 00111101->10111111 '^': 。位元間作運算,只有當1&0或0&1時結果才為1. 。ex. 10010011 ^ 00111101->10101110 ㄧ個常用的integer2Binary涵式: char* Int2Bin(int n, char *pb){     int len = 8*sizeof(int);     int i;     for(i=1;i<=len;i++, n>>=1)     {           pb[len-i]=(1&n)|'0'      }      pb[len+1]='\0'; }

[C] 關於 shared library

今晚來複習一下shared library的建置好了, 主要有三個步驟: 1)建立 object codes (.h跟.c檔) 2)建立 library > root#gcc -Wall -fPIC -c test.c -Wall:顯示warning message -fPIC:compile產生position independent code. *PIC大小寫有差異. >> 產生 test.o > root#gcc -shared -Wl,-soname,libtest.so.1 -o libtest.so.1.0 *.o -shared:產生為shared object -Wl:將參數傳給linker, 這裡的參數是 "-soname libtest.so.1". 需要注意的是逗號之間不可以留空白!!! >> 產生 libtest.so.1.0 3)建立 link (optional) 通常會建立 libtest.so 跟 libtest.so.1 >> ln -sf / path / to /libtest.so.1.0 libtest.so >> ln -sf / path / to /libtest.so.1.0 libtest.so.1 libtest.so 是提供其他檔 ex. abc.c檔要compile時, 做naming conversion用 (即 -ltest) libtest.so.1 則是提供執行 abc 時, 做 runtime binding用。 如此在編譯其他的abc.c檔時 >> gcc -Wall -L/ path / to / libtest.so -ltest test.c -o test 然後在執行abc時, 記得將 path / to / libtest.so 加入 $LD_LIBRARY_PATH 中。 當然也可以修改ld.so.conf或執行時指定.so路徑。 另外可以下 ldd test 檢查 executable 所link 的library是否正確。

[c++] namespace

寫過一些些c++, java跟 python 但是對於物件導向(Object-Orientated) 的解釋,一直說不上話 今天來複習一下... 1. 命名空間 namespace 這是一開始寫c++時都會停住的問題,就竟什麼是命名空間? 為什麼需要有命名空間? 看了網上諸多解釋後,我自己認為是由於程式越長越大時,常會有變數、函式或類別名稱 相同的情況,甚至同類別名稱又同變數名稱等,這時後容易混淆,甚至覆蓋掉先前的定義。 c++提供一個空間的概念,即在各自的空間上定義的任何變數、函式,彼此是互斥的。 使用的方式是 namespace NAME {     // method, variable, etc. } ex. #include using namespace std; namespace cat{   int shout;   int act; } namespace dog{   double shout;   double act; } int main(void) {   cat::shout = 2   cat::act = 4   dog::shout = 1   dog::act = 3      cout< <   cout< <   cin.get();   return 0; } 亦可寫作兩個file ex. cat.h namespace cat{    int shout;    int act; } main.cpp #include #include "cat.h" using namespace std; int main(void) {     cat::shout = 9;     cat::act = 2;     cout << cat::shout + cat::act ...

[c++] 使用TinyXml

今天跟學弟討論XML的document object 屬性數目問題。 首先回憶一下python DOM所描述的XML由上到下分成 Document -> Element(s) ->NodeList -> Node(s) 在python 裡頭,因為Document object是minidom lib自己建的, 取出某個Node的Attr或Text很容易。 而在TinyXml 裡頭要找做到相同的事情: 0. TiXmlDocument doc('mytest.xml') 建立Document obj 1. 使用 doc.Parse('mytest_xmlstring') 讀入xml並建立XML-tree 2. 要取得Element(s)可用     TiXmlElement *elem = doc.FirstChildElement() or     TiXmlElement *elem = doc.FirstChildElement('selected_element_name') 3. 要找某個Element obj裡頭特定Node的Attr or Text 可用   *Assume only one Element in elem   sp_attr_name, sp_attr_value    TiXmlAttribute *attr = elem->FirstChildAttribute('specified_element_name')   while (1):       if (!attr) break;       else{            if (attr->Name() == sp_attr_name) and (attr->Value() == sp_attr_value){                fprintf(stdout, "match...

[c] 如何在linux上使用 getch()

剛剛同學問我的問題,我也沒在linux上實做c,但總覺得這問題一定很常見, 所以就把他註記下來。 主要步驟是 0. include curses.h  [ getch()在裡頭 ] 1. 使用initscr() [ WINDOW *W = initscr() ] 2. ch = getch() 3. endwin() 另一個則是透過posix實做 getch() http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!5092.entry

[c] memory 相關的函式(memset, memcpy, memmove)

memset void * memset ( void * ptr, int value, size_t num ); ptr      :為destination address 的pointer value :想要set的值。(居然是type int. 表示是0~255(unsign char)) num   :number of bytes 這表示一次只能set 1bytes,然後寫入num個。(這真是沒效率 囧...) 這邊說錯了, 要reset值的長度用sizeof(ptr)就好了... (05/04/2011) memcpy void * memcpy ( void * destination, const void * source, size_t num ); 這ok,不過若source在copy時被overwrite時會是問題。 memmove void * memmove ( void * destination, const void * source, size_t num ); memmove跟memcpy狠像,唯一的差別是在於它能保證source不會被overwrite。 另外關於w32api中mmap的使用可以參照 這裡 ,另外也需要參考 MSDN 1) 主要有三個步驟CreateFile(), CreateFileMapping() 跟MapViewOfFile() 2) mapping的blocksize需為dwAllocationGranularity的倍數。 3) 主要是為了處理大檔(>=2**32, 2G以上),由於他的maxsize有Hi跟Low之分,要用 Hi = offset>>32, Low = offset & 0xffffffff 以轉成64bits. 4) MapViewOfFile Object 回傳ptr, 所以需要使用buffer來儲存欲處理的 data