Sunday, November 21, 2021

[C++] const volatile restrict

compiler 的最佳化編譯,為了增快程式速度,

有時候會很聰明的將程式碼編譯成和原 code 不同,但意思相同的 object code

如下:

for (int i = 0; i < 10000; i++) {

    a = 5;

   a =  a * i;

}

compiler 可以簡化成下列一條敘述:

a = 5 * 9999;

編譯器最佳化,就讓程式變得更有效率。

 

但是當我們某些程式片段不希望做最佳化的時候呢? 就要使用 volatile 關鍵字

volatile 是 C 的關鍵字,用來修飾資料型態,是告訴 compiler 不要對這一個變數的程式碼區段做最佳化。

volatile 表明某個變量的值可能在外部被改變,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器裡的備份

它可以適用於基礎類 型如:int,char,long......也適用於C的結構和C++的類。當對結構或者類對象使用volatile修飾的時候,結構或者類的所有成員 都會被視為volatile.

volatile 使用時機

該關鍵字在多線程環境下經常使用,因為在編寫多線程的程序時,同一個變量可能被多個線程修改,而程序通過該變量同步各個線程。

簡單示例:


復制代碼代碼如下:

DWORD __stdcall threadFunc(LPVOID signal)

{

int* intSignal=reinterdivt_cast(signal);

*intSignal=2;

while(*intSignal!=1)

sleep(1000);

return 0;

}


該線程啟動時將intSignal 置為2,然後循環等待直到intSignal 為1 時退出。顯然intSignal的值必須在外部被改變,否則該線程不會退出。但是實際運行的時候該線程卻不會退出,即使在外部將它的值改為1,看一下對應的偽匯編代碼就明白了:

 


mov ax,signal

label:

if(ax!=1)

goto label


對於C編譯器來說,它並不知道這個值會被其他線程修改。自然就把它cache在寄存器裡面。C 編譯器是沒有線程概念的,這時候就需要用到volatile。volatile 的本意是指:這個值可能會在當前線程外部被改變。也就是說,我們要在threadFunc中的intSignal前面加上volatile關鍵字,這時 候,編譯器知道該變量的值會在外部改變,因此每次訪問該變量時會重新讀取,所作的循環變為如下面偽碼所示:

label:

mov ax,signal

if(ax!=1)

goto label


注意:一個參數既可以是const同時是volatile,是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。

restrict 

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);


https://www.itread01.com/content/1550372781.html

https://liquid0118.pixnet.net/blog/post/48494846

Friday, November 12, 2021

c++ Introduction

C++ 是在 C 語言的基礎上開發的一種集面向對象編程、泛型編程和過程化編程於一體的程式語言。

命名空间


//現代的C++程式
#include <iostream>
using namespace std ;
int main() {
//程式碼
return 0 ;
}

//傳統的C++程式
#include <iostream.h>
int main() {
//程式碼
return 0 ;
}


C++學習之路(15)——C++ 庫資源大全(太全了)

Tuesday, November 9, 2021

[字串處理] unsigned char myVar[10] to std::string

 #include <iostream>

#include <stdio.h>

#include <string.h>


int main()

{

    std::string strList;

    int itemCount = 10;

    int u8Index = 0;

    unsigned char myVar[10] = "abcdefg";


    for(u8Index = 0; u8Index < itemCount; u8Index++)

    {

    std::string res(myVar, myVar+strlen((char*)myVar));

    strList.append(res).append("\n");

    }

    std::cout << strList ;

}

[c++] 字串處理

[C++] string 和 char[]互轉 (string and char[] transform)

unsigned char myVar[10] to std::string

 实战c++中的string系列--std:vector<char> 和std:string相互转换(vector to stringstream)

C++程式設計 —— 字串分割與連線

Sunday, November 7, 2021

[技術名詞解釋] 函數指標

函式名稱會自動轉為指標

型態由傳回值型態與參數列決定

重載函式具有不同的簽署,因此在指定時,雖然具有相同名稱,然而依函式指標的型態不同,編譯器會選擇對應的重載函式:


函式指標可以用來傳遞函式



reference

https://openhome.cc/Gossip/CppGossip/FunctionPointer.html


[技術名詞解釋] index

解釋Little-Endian, Big-Endian (資料放進記憶體位元組順序)

函數指標

[C] continue

C 語言程式記憶體配置概念

[程式演算法] 計算二進位任意數含有多少個位元為1?

 #include <stdio.h>

#include <stdlib.h>

int bitcount(unsigned int);

int main(){

    int count = 0, a;

    a = 1023;

    count = bitcount(a);

    printf("%d有%d個位元為1\n\n", a, count);


    system("pause");

    return 0;

}

int bitcount(unsigned int n)

{

   int count = 0 ;

   while (n)

   {

      count++ ;

      n &= (n - 1) ; //關鍵演算之處

   }

   return count ;

}

[程式演算法] 1, 1, 2, 3, 5, 8...,要你求出第n項的值,分別用遞迴和迭代

B = 1

A = 1

1, 1, 2, 3, 5, 8

N = ??

N = 0


F(N)

F(0) = 0

F(1) = 1

F(2) = 2

F(3) =  F(1) + F(2) 

F(4) =  F(2) + F(3) 


#include <stdio.h>

long F(long n)

{

 if(n<=2) return 1;

 return F(n-1)+F(n-2);

}


void main()

{

 long n;

 scanf("%ld",&n);

 printf("%ld", F(n));

}


[程式演算法] y=1^2+2^2+.....n^2,不能用乘法 只能用一層loop

y=1^2+2^2+.....n^2

y = 1 + 4 + 9 + 16...


1 =  0 + (1 + 0)

5 = 1 + (3 + 1)

14 = 5 + (5 + 4)

30 = 14 + (7+ 9)


var sum = 0

var temp = 1

 var loopvalue = 0;

for (i = 1; i <= n; i++) {

  sum = sum + (temp  + loopvalue );

  loopvalue = (temp  + loopvalue );

  temp = temp + 2;

}

[程式演算法] index

 y=1^2+2^2+.....n^2,不能用乘法 只能用一層loop

 1, 1, 2, 3, 5, 8...,要你求出第n項的值,分別用遞迴和迭代

計算二進位任意數含有多少個位元為1?


n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能