2020年5月24日 星期日

Cpp - &

C++ 的 &


    C++ 的 & 比起 C 語言的提取位置,還多了宣告引用 必須在定義時候就進行初始化 )。
    int a = 5;
    int &b = a;
    std::cout << "a value\t\t" << a << "\n";
    std::cout << "a address\t" << &a << "\n";
    std::cout << "b value\t\t" << b << "\n";
    std::cout << "b address\t" << &b << "\n";
    int c = 50;
    b = c;
    std::cout << "a value\t\t" << a << "\n";
    std::cout << "a address\t" << &a << "\n";
    std::cout << "b value\t\t" << b << "\n";
    std::cout << "b address\t" << &b << "\n";
    std::cout << "c value\t\t" << c << "\n";
    std::cout << "c address\t" << &c << "\n";
a value         5
a address       0x61ff08
b value         5
b address       0x61ff08
a value         50
a address       0x61ff08
b value         50
b address       0x61ff08
c value         50
c address       0x61ff04


參考資料 :

C/C++ - 左值、右值 ( lvalue、rvalue )

lvalue、rvalue 基本概念

左值 (lvalue) : 一個佔據某個特定記憶體的值。
右值 (rvalue) : 一個 expression 結束後就消失的值。
基本上這兩個定義包含了全部的值,非左即右,非右即左。
    int var = 4;    // var 參數佔據記憶體 = lvalue
    4 = var;        // 4 不佔據記憶體 = rvalue
    (var + 1) = 4;  // var + 1 也不佔據記憶體 = rvalue
    以上 2 跟 3 行會報錯,lvalue required as left operand of assignment。表示這個賦值程式碼錯在給不存在的記憶體空間賦值。所以只要是 lvalue 就能賦予值,即使是 function 也一樣,下面的 function 引用一個左值 ( globalvar ),所以可以賦予值。
    int globalvar = 20;

    int &foo() {
        return globalvar;
    }

    int main() {
        foo() = 10;
        std::cout << globalvar; // 10
        return 0;
    }

lvalue、rvalue 轉換


    左值能直接的轉換成右值,但右值卻不行,這時就會需要 ' * ' 。
    int a = 1;
    int b = a + 1;  // 這裡的 a 被直接視為右值
    int arr[] = {a, b};
    int *p = arr;
    *(p + 1) = 10;  // 利用 * 將右值 (p + 1) 傳換成左值


參考資料 :

2020年5月23日 星期六

C/C++ - Const

const 基本用途


    告知編譯器這個值為「常數」無法被修改。
  • 一般作用
        const int index = 5;
        index = 8; // error: assignment of read-only variable 'index'
  • 作用於 *
        // const pointer
        char * const constptr = initptr;
        *constptr = 1;              // 改變其 value OK
        constptr = otherptr;        // 改變其  addr Error
    
        // const value
        const char * constval = "const value";
        *constval = "nomal value";  // 改變其 value Error
        constval = otherptr;        // 改變其  addr OK
    
        // const pointer & const value
        const char * const consteverything = "ulti - const";

const 常見用途 : const&

在 C++ 可能常常看到 void function (type_Name const&);
"type_Name const&" 是可以寫成 "const type_Name &"
    int i = 10;
    const int &r = i;   // reference to const
    ++i;                // i 仍然可以修改
    ++r;                // r 不行 (expression must be a modifiable lvalue)
    通常追求效率的 C++ 工程師,會選擇 pass by reference 來防止程式做不必要的 Copy,這時 const 通常就會出現,來確保原始 value 不會被亂改。且 const 的出現可以使 call function 時,使用 rvalue。
    std::vector mySort(std::vector const &str)
    {
        std::vector r(str);
        std::sort(r.begin(), r.end());
        return r;
    }
    mySort({"abc", "def", "xyz"});

相關文章 :
C/C++ - 左值、右值 ( lvalue、rvalue )
讀書心得 - C++ Primer (5th Edition) - Chapter 2 (2)

參考資料 :

C/C++ - Function Pointer 應用 CallBack Function

Function Pointer 應用 CallBack Function


    有了 Function Pointer 就意味著,Callback Function 能被實現。    
Callback Function : 
A 跟 B 講 "看到 C 就打電話給我"
打電話給 A = Callback Function
    main.cpp ( A )
    int 
    main () {
        // 從 0 數到 10000000,中間請回報進度 % 數
        zeroTo(1000000, ShowPercentage);
        return 0;
    }
    zeroTo ( B ) 每數一個數字 ( 看到 C )
    void 
    zeroTo (size_t targetNumber, CallBackFuncPtr func) 
    {
        for (size_t i = 0; i < targetNumber; i++){
            func((i * 100) / targetNumber);
        }
    }
    ShowPercentage ( 打電話給 A )
    typedef void (*CallBackFuncPtr)(size_t);
    void ShowPercentage(size_t percentage)
    {
        std::cout << "\rProcessing :\t" << percentage << "%";
    }


相關文章 : 

2020年5月12日 星期二

心情日記 2019/05/12

好久沒寫日記,整理 tag 才發現我有寫這種東西。

根據勒布朗克法則:待會兒等於永不。即使現在是上班時間我也照寫 ( 其實只是讀 spec 讀到煩躁,想呼吸新鮮空氣 )。



寫 blog 現在對我的生活來說是提神良品,非常適合我這種六日只想待在家的廢才。

即使一開始有一篇沒一篇地寫,如此懶散的頻率,文章數還是來到了三位數。

看著已發表的文章,深深理解 1 > 0 的理論,不是指冠軍戒指,而是 " 累積 "。



我是一個沒啥雄心壯志的人,也沒有一個夢想讓我想灌注一身的努力去實現,除了財富自由。

但我想我開始能接受這樣的自己,沒有夢想的工程師,很廢但依然能享受人生。

2020年5月10日 星期日

C 語言 - CLI ( Command Line Interface ) 設計 (1)

CLI 命令列介面


    在設計 CLI 的程式時,最好的方法是遵從 IEEE Std 1003 ( POSIX ) 對 program 的 command-line options 之規範。所以用 getopt 去做 parse command-line 是最簡單的,有一點要注意的是 GNU 提供的 getopt 支援 " -- ",這個 POSIX 沒有規範。

常見的 Usage 設計

    Usage : 
        my_program tcp <host> <port> [--timeout=<seconds>]
        my_program serial <port> [--baud=9600] [--timeout=<seconds>]
        my_program (-h | --help)
    參數
    my_program   : program name
    tcp   : commands
    -h, --help   : options
    <host>   : arguments

    符號
    [ ]   : optional
    ( )   :  required
     |   :  mutually exclusive
    ...   :  repeating elements

Options 設計


    在設計長命名的 option ( " -- " ),最好需要有一個相對短命名的 option ( " - " ),example : -h, --help。

    每隻程式最好都要有 --help 跟 --version


參考資料 :

2020年5月3日 星期日

Makefile 筆記 (1)

Makefile 範本 (OS: Windows)

    教學網路上很多,這裡記錄下我目前測試程式碼的 Makefile
    # 通用編譯參數
    CC     = gcc
    CFLAGS = -g -Wall

    # Objects = 為要與 main 連結的 .o 檔
    OBJECTS = hello.o pointer.o unsignedChar.o struct.o
    SOURCE_PATH  = source/
    INCLUDE_PATH = include/

    program: main.o ${OBJECTS}
        ${CC} ${CFLAGS} -o program.exe main.o ${OBJECTS}

    # 告訴編譯器 在當前目錄下找 main.c
    main.o: main.c
        $(CC) -I$(INCLUDE_PATH) $(CFLAGS) -c $<

    # 告訴編譯找 在 source/ 找 %.c 在 include/ 找 %.h
    %.o: $(SOURCE_PATH)%.c $(INCLUDE_PATH)%.h
        $(CC) -I$(INCLUDE_PATH) $(CFLAGS) -c $<

    clean:
        del main.o ${OBJECTS} program.exe

-I$(INCLUDE_PATH)

    這個是告訴程式碼在 include 時可以在這個目錄找,所以我的 main.c 在 include 時能如下,而不用#include "include/hello.h"
    #include "hello.h"
    #include "struct.h"
    #include "pointer.h"
    #include "pthread.h"
    #include "unsignedChar.h"
相關文章 :

C 語言 - warning: left shift count >= width of type

warning: left shift count >= width of type

    一般來說,就是 shift 的 bit 大於資料型態的 bit 數。但有時使用 unsigned long 仍然會出錯,因為 unsigned long 會依照系統的不同,有時是 32 bit 有時是 64 bit,所以這時用 unsigned long long 較為安全 ( 保證 64 bit )。


參考資料 :
https://stackoverflow.com/questions/4201301/warning-left-shift-count-width-of-type

C 語言 - struct array 初始化 ( Initializing array of structures )

初始化 struct array

    struct student
    {
        char* name;
        int grade;
        int id;
    };

1. 依照當初宣告的順序

    struct student myStudents[] = {
        {"Henry", 3, 1},
        {"Marry", 3, 2}
    };

1. 依照當初宣告的名子

    struct student myStudents[] = {
        {.id = 1, .grade = 3, .name = "Henry"},
        {.id = 2, .grade = 3, .name = "Marry"}
    };

Output

  printf("ID : %d-%d\tName : %s\n", myStudents[0].grade, myStudents[0].id, myStudents[0].name);
  printf("ID : %d-%d\tName : %s\n", myStudents[1].grade, myStudents[1].id, myStudents[1].name);

  // ID : 3-1        Name : Henry
  // ID : 3-2        Name : Marry


參考資料 :
https://stackoverflow.com/questions/18921559/initializing-array-of-structures

Popular Posts