管道FIFO的創建與使用[未完成]

前提

運行環境:Qt5.8.0+Linux虛擬機+Desktop Qt 5.8.0 GCC 64bit

FIFO

它是一種文件類型,在文件系統中可以看到。程序中可以查看文件stat結構中st_mode成員的值來判斷文件是否是FIFO文件。創建一個FIFO文件類似於創建文件,FIFO文件就像普通文件一樣。
FIFO的通信方式類似於在進程中使用文件來傳輸數據,只不過FIFO類型文件同時具有管道的特性。在數據讀出時,FIFO管道中同時清除數據。
在文件系統中作爲一個特殊的設備文件而存在的。

使用到的函數基本認識

字節相關的換算

  • 字節相關的換算1

1M=1048576字節,換算過來1字節=1/1048576M約爲0.000001M。
MB:全稱兆字節(MByte)是計算機存儲容量單位,一般用字節(Byte)、千字節(KB)、兆字節(MB)、吉字節(GB)、太字節(TB)、拍字節(PB)、艾字節(EB)、澤它字節(ZB,又稱皆字節)、堯它字節(YB)表示。
位:數據存儲的最小單位。每個二進制數字0或者1就是1個位。
計算機容量單位的換算關係是:
1Byte字節=8bit位
1KB=1024B
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
1EB=1024PB
1ZB=1024EB
1YB=1024ZB

聲明與定義

  • 聲明與定義2
  • 變量:
    • 聲明(declaration)用於向程序表明變量的類型和名字。
    • 變量的定義(definition)用於爲變量分配存儲空間,還可以爲變量指定初始值。在程序中,變量有且僅有一個定義。 不定義變量的聲明包括對象名、對象類型和對象類型前的關鍵字extern。
    • 定義也是聲明:當定義變量的時候我們聲明瞭它的類型和名字。
    • PS:extern是聲明不是定義,也它不分配存儲空間。事實上它只是說明變量定義在程序的其他地方【即 在沒有賦值的情況下,變量前加上關鍵字extern一定爲聲明】。程序中變量可以聲明多次,但只能定義一次。
    • 如果聲明有初始化式,就被當作定義,即使前面加了extern。但是隻有當extern聲明位於函數外部時,纔可以被初始化。
extern int i; //聲明,不是定義,因爲extern提示i這個變量在別的地方定義過了
       int i2; //聲明,也是定義, 不初始化
       int i3 = 10; //聲明且定義, 同時進行初始化
       得出:有類型、變量名爲聲明,給予默認值【系統賦予】/初始值【自定義】爲定義  
  • 函數:
    • 帶有{ }的函數就是定義。
    • 不帶有{ }的函數就是聲明。
extern double max(double d1, double d2);  //聲明
       double max(double d1, double d2)//定義
       {
          return d1>d2?d1:d2;       
       }

字符串末尾爲什麼加’\0’ 或 爲什麼初始化字符串時用’\0’

  • 字符串末尾爲什麼加’\0’ 或 爲什麼初始化字符串時用’\0’3
  • '\0’就是8位的00000000,因爲字符類型中並沒有對應的這個字符,所以這麼寫。在數值類型裏就代表數字0。
  • '\0’是轉譯字符,意思是告訴程序,這不是字符0,我要的是數字0的2進制直接放進來,因爲acsii碼的0可不是00000000,若0爲字符,十進制爲48,若0爲十進制,字符爲NUL(null)【解釋爲空字符】。
  • '\0’就是 字符串結束標誌。若不人爲加上,C編譯系統也會自動加上的。所以一般在用字符串賦初值時無須指定數組的長度, 而由系統自行處理。
  • 0與’\0’是等價的。

‘\0’

  • ‘\0’ 4
  • c++中字符串以字符‘\0’結尾,所以每個字符串都有額外一個字符的開銷。
    如:char str[10]; strcpy(str,"0123456789")
    分析:因爲“0123456789”有十個字符,但是末尾自動加一個’\0’字符,因此它的實際長度是11個字節。所以,如果要複製該字符串,至少需要一個長度爲11個字節的數組。
  • strlen()計算長度時不考慮末尾的’\0’,所以容易引發“內存溢出”,解決:strlen(數組長度-1)纔是真正存字符的長度,總之留一個空位出來就對了!
	char s[] = "10";
    printf("%s\n", s);
    printf("s[1]:%d\n", s[1]);
    printf("s[2]:%d\n", s[2]);
    printf("s[1]:%c\n", s[1]);
    printf("s[2]:%c\n", s[2]);

    char u[] = {"hello"};
    cout << sizeof(u) / sizeof(*u) << endl;
    char v[] = "hello";
    cout << sizeof(v) / sizeof(*v) << endl;

打印結果

文件權限

  • 文件權限5
const S_IRUSR = %0100000000;//用戶讀權限
const S_IWUSR = %0010000000;//用戶寫權限
const S_IXUSR = %0001000000;
  • 其中:const S_IRWXU = S_IRUSR or S_IWUSR or S_IXUSR
int fd = open(dev_name, O_RDWR,S_IRWXU);

文件描述符

  • 文件描述符6

內核(kernel)利用文件描述符(file descriptor)來訪問文件。文件描述符是非負整數。打開現存文件或新建文件時,內核會返回一個文件描述符。讀寫文件也需要使用文件描述符來指定待讀寫的文件。
每一個文件描述符會與一個打開文件相對應,同時,不同的文件描述符也會指向同一個文件。相同的文件可以被不同的進程打開也可以在同一個進程中被多次打開。系統爲每一個進程維護了一個文件描述符表,該表的值都是從0開始的,所以在不同的進程中你會看到相同的文件描述符,這種情況下相同文件描述符有可能指向同一個文件,也有可能指向不同的文件。
在linux系統中打開文件就會獲得文件描述符,它是個很小的正整數。每個進程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是這個表的索引,每個表項都有一個指向已打開文件的指針。
舉例:

int f1,f2 ;
f1 = open(“test1”,O_RDONLY,0) ;
close(f1) ;
f2 = open(“test2”,O_RDONLY,0) ;
printf(“f2=%d\n”,f2) ;
最後打印結果爲 3

分析:
f1,f2代表的是文件描述符,Unix進程從生命週期開始時,打開的描述符賦給stdin(描述符0),stdout(描述符1),stderr(描述符2)。open函數總是返回最低的未打開的描述符,所以第一次調用open會返回描述符3。調用close函數則會釋放描述符3。如果再調用open函數則文件描述符又會是3。若爲釋放之前的文件描述符3,則再打開一個文件時,文件描述符就變爲4。以此類推……

已知的文件描述符

Linux的文件描述符:

文件描述符 通道名 描述 默認連接 用途
0 stdin 標準輸入 鍵盤 read only
1 stdout 標準輸出 終端 write only
2 stderr 標準錯誤 終端 write only
3以上 filename 其他文件 none read and/or write

補充:標準輸入輸出說明:
stdin,標準輸入,默認設備是鍵盤,文件編號爲0
stdout,標準輸出,默認設備是顯示器,文件編號爲1,也可以重定向到文件
stderr,標準錯誤,默認設備是顯示器,文件編號爲2,也可以重定向到文件

其他

sizeof(…)

  • sizeof(…)7
  1. 指針與靜態數組的sizeof操作
    指針均可看爲變量類型的一種,所有指針變量的sizeof操作結果均爲4 。【在32位計算機中,一個指針變量的返回值必定是4(注意結果是以字節爲單位),在64位系統中指針變量的sizeof結果爲8。】
  2. 使用sizeof時string的注意事項
    string s=“hello”;
    sizeof(s)等於string類的大小,sizeof(s.c_str())得到的是與字符串長度。
    總體上遵循兩個原則:
    (1)整體空間是 佔用空間最大的成員(的類型)所佔字節數的整倍數
    (2)數據對齊原則----內存按結構成員的先後順序排列,當排到該成員變量時,其前面已擺放的空間大小必須是該成員類型大小的整倍數,如果不夠則補齊,以此向後類推。。。。。
  3. 注意:數組按照單個變量一個一個的擺放,而不是看成整體。如果成員中有自定義的類、結構體,也要注意數組問題。

證明sizeof不是函數,他只是操作符或運算符

strlen(…)

  • strlen(…) 8

所作的僅僅是一個計數器的工作,它從內存的某個位置(可以是字符串開頭,中間某個位置,甚至是某個不確定的內存區域)開始掃描,直到碰到第一個字符串結束符’\0’爲止,然後返回計數器值。

  • 原型:extern unsigned int 或 size_t strlen(char *str );
  • 舉例:
  char str[50];
  int len; 
  strcpy(str, "This is yiibai.com"); 
  len = strlen(str);
  printf("Length of %s is %d", str, len);
  
打印結果: Length of This is yiibai.com is 26
  • 功能:參數str 是字符串;計算字符串str的長度,但不包括終止空字符’\0’。
  • 返回值:這個函數返回字符串的長度。

其他

size()與length()均爲string類的成員函數,其中length()沿用C的風格,size則是引入STL後,作爲STL容器的屬性存在的,二者返回的結果一致。
如:string a="hellow";調用結果:a.length()=6;a.size()=6;

區別

  • strlen計算字符數組的字符數,以“\0"爲結束符,不計算“\0"爲數組元素,只求字符串的長度。
  • sizeof()計算數據(數組、變量、類型、結構體等)所佔空間,用字節數表示。【sizeof實際上是獲取了數據在內存中所佔用的存儲空間,以字節爲單位來計數。C語言會自動在在雙引號"“括起來的內容的末尾補上”\0"代表結束,ASCII中的0號位也佔用一個字符。】
  • sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以”\0”結尾的。sizeof還可以用函數做參數,如:short f();printf("%d\n", sizeof(f()));,輸出的結果是返回值的類型的大小, 即sizeof(short)=2。
  • 數組做sizeof的參數不退化,傳遞給strlen就退化爲指針了。
  • sizeof是取字節運算符(C++ 關鍵字),strlen是函數。

sizeof與strlen的區別

操作符與運算符的區別
  • 操作符與運算符的區別9

操作符和運算符在英文裏都叫operator,

  1. 操作符是嵌在每一條指令中的,換句話說,指令系統的每一條指令都有一個操作符。我理解是計算機系統中的術語。如: =(賦值),==(判斷相當)等等。
  2. 運算符是數學中的術語。主要是指數之間的運算方式。如 + - * / %,但不包括 = (賦值)這樣的操作符。

perror()

  • perror() 10
  • 原型:void perror(const char *str);——把一個描述性錯誤消息輸出到標準錯誤 stderr,首先輸出字符串 str,後跟一個冒號,然後是一個空格,接着是對應於errno值的出錯信息,最後是一個換行符。【#include<stdio.h>】
  • 舉例:perror(“perror”);——結果如下圖
  • 功能:str – 這是 C 字符串,包含了一個自定義消息,將顯示在原本的錯誤消息之前。
  • 返回值:該函數不返回任何值。

strerror()

  • 原型:char *strerror(int errnum);——將errnum(它通常就說errno值)映射爲一個出錯信息字符串,並返回此字符串的指針。【#include <string.h>】
  • 舉例:printf(“fork error:%s\n”,strerror(errno));——結果如下圖
  • 功能:只是將errno對應的錯誤消息字符串返回,要怎樣處理完全由你自己決定。
    兩函數的使用的區別

ferror()

feof()

errno

  • errno 11
  • 表示:是error number的縮寫,是一個全局變量。errno宏定義爲一個int型態的左值, 包含任何函式使用errno功能所產生的上一個錯誤碼。
  • 意義:Linux系統對各種常見的錯誤做了個編號,當函數執行錯誤時,函數會返回一個特定的errno編號(int 類型)來告訴我們這個函數哪裏錯了。
  • 使用:Linux系統提供了一個函數perror(print errot),perror函數內部會讀取errno並且將這個數字轉成對應的錯誤字符串,然後打印出來。【perror是將errno對應的錯誤消息的字符串打印到標準錯誤輸出上】
    errno的使用原理

區別

read(…,…,…)

  • read(…,…,…)12
  • 原型:ssize_t read( int filedes, void *buf, size_t nbytes);——從buf中讀取nbytes長度給filedes【#include<unistd.h>】
  • 舉例:char buf[10];int fd= open("/dev/tty", O_RDONLY | O_NONBLOCK);int n = read(fd, buf, 10);——只讀且非阻塞的模式來open這個路徑的dev文件夾下的指定文件tty,表示當前打開的終端設備
  • 功能:讀入指定長度的數據。從 filedes 中讀取數據到 buf 中,nbytes 是要求讀到的字節數。當從終端設備讀時,通常一次最多讀一行。ssize_t 提供帶符號的返回值,size_t不帶符號。
  • 返回值:
      > 0: 實際讀到的字節數
      = 0: 讀完數據(讀文件, 管道, socket末尾–>對端關閉, 對端未關閉會一直等待)
      -1: 異常:
        errno == EINTR被信號中斷, 重啓或者退出
        errno == EAGAIN或者EWOULDBLOCK以非阻塞方式讀, 並且沒有數據
        其他值: 出現錯誤perror eixt

與fgets(…,…,…)的區別

fgets(…,…,…)
  • fgets(…,…,…)13
  • 原型:char *fgets(char *s, int n, FILE *stream);——讀取n個長度的文件數據到數組s
  • 舉例:fgets(str, sizeof(str), stdin);——str爲數組首地址,sizeof(str)爲數組大小,stdin表示我們從鍵盤輸入數據。
  • 功能:從文件指針stream中讀取字符,存到以s爲起始地址的空間裏,知道讀完N-1個字符,或者讀完一行。
  • 注意:調用fgets函數時,最多隻能讀入n-1個字符。讀入結束後,系統將自動在最後加’\0’,並以str作爲函數值返回。
gets(…,)
  • 原型:char *gets(char *buffer);——讀取字符到數組
  • 舉例:gets(str);——str爲數組名。
  • 功能:從鍵盤上輸入字符,直至接受到換行符或EOF14時停止,並將讀取的結果存放在buffer指針所指向的字符數組中。讀取的換行符被轉換爲null值,做爲字符數組的最後一個字符,來結束字符串。
  • 注意:gets函數由於沒有指定輸入字符大小,所以會無限讀取,一旦輸入的字符大於數組長度,就會發生內存越界,從而造成程序崩潰或其他數據的錯誤。
getchar()
區別
  • 區別 15
  • gets函數沒有限制讀入的個數,這很可能會導致程序向未知的內存空間寫入數據,而導致程序出錯。
  • fgets函數中第二個參數限制了讀取的個數,這也解決了gets函數存在的問題,但要注意fgets函數只會讀取n-1個字符(如果遇到換行符會更少),並在最後添加字符串結束標誌,而且,fgets也會將換行符讀入。
  • read與fget:
	int stdin=0;
	char buffer[BUFFER_SIZE];
	 /*從標準輸入中讀取輸入的內容,兩種函數實現效果一樣*/
	fgets(buffer, sizeof(buffer), stdin);
	read(0,buffer,sizeof(buffer));//讀串口信息,在終端中輸入字符,開發板上運行了的程序可以讀取並進行指定的處理
區別

write(…,…,…)

  • write(…,…,…)16
  • 原型:ssize_t write(int fildes, const void *buf, size_t nbyte);.——從buf內寫入nbyte字節給fildes【#include<unistd.h>】
  • 舉例:
  • 功能:從 buf 中寫數據到 filedes 中,nbytes 是相求寫入的字節數。
  • 返回值: 返回實際寫出的字節數, 0表示什麼也沒有寫

open(…,…,…)

  • open(…,…,…)17
  • 原型:int open(const char pathname, int oflag, … / mode_t mode */);——【#include <fcntl.h>】
  • 舉例: 阻塞方式打開:int fd = open("/dev/tty", O_RDWR|O_NONBLOCK); 非阻塞方式打開:int fd = open("/dev/tty", O_RDWR);
  • 功能:函數第一個參數是指向文件名的指針(一般填寫路徑名),第二個參數是文件的打開模式標記,第三個參數(…)僅當創建新文件時才使用,用於指定文件的訪問權限位(access permission bits)。
    oflag 用於指定文件的打開/創建模式,這個參數可由以下常量(定義於 fcntl.h)通過邏輯或構成。
模式 描述
O_RDONLY 只讀模式
O_WRONLY 只寫模式
O_RDWR 讀寫模式

打開/創建文件時,至少得使用上述三個常量中的一個。以下常量是選用的:

模式 描述
O_APPEND 每次寫操作都寫入文件的末尾
O_CREAT 如果指定文件不存在,則創建這個文件
O_EXCL 如果要創建的文件已存在,則返回 -1,並且修改 errno 的值
O_TRUNC 如果文件存在,並且以只寫/讀寫方式打開,則清空文件全部內容
O_NOCTTY 如果路徑名指向終端設備,不要把這個設備用作控制終端。
O_NONBLOCK 如果路徑名指向 FIFO/塊文件/字符文件,則把文件的打開和後繼 I/O設置爲非阻塞模式(nonblocking mode)

阻塞與非阻塞

  • 阻塞與非阻塞18
  • 非阻塞
    • O_NONBLOCK和O_NDELAY所產生的結果都是使I/O變成非阻塞模式(non-blocking),在讀取不到數據或是寫入緩衝區已滿會馬上return,而不會阻塞等待。
    • 它們的差別在於:在讀操作時,如果讀不到數據,O_NDELAY會使I/O函數馬上返回0,但這又衍生出一個問題,因爲讀取到文件末尾(EOF7)時返回的也是0,這樣無法區分是哪種情況。因此,O_NONBLOCK就產生出來,它在讀取不到數據時會回傳-1,並且設置errno爲EAGAIN。
    • 一般使用O_NONBLOCK。

close(…,…,…)

access(…,…)

mkfifo(…,…,…)

  • mkfifo(…,…,…)19
  • 原型:int mkfifo(const char * pathname,mode_t mode);——【#include<sys/types.h> #include<sys/stat.h>】
  • 舉例:int ret=mkfifo("/media/my_write_read_fifo",O_CREAT|O_EXCL|660);或mkfifo("/media/my_write_read_fifo",0666|S_IFIFO);
  • 功能:依參數pathname建立特殊的FIFO文件,該文件必須不存在,而參數mode爲該文件的權限(mode%~umask),因此 umask20值也會影響到FIFO文件的權限。Mkfifo()建立的FIFO文件其他進程都可以用讀寫一般文件的方式存取。

Linux文件訪問權限

  • Linux文件訪問權限 21

#include 《sys/stat.h》作用

  • #include 《sys/stat.h》作用 22
  • 是unix/linux系統定義文件狀態所在的僞標準頭文件。

  • 一般頭文件在/usr/include下面,這裏是標準C程序頭文件,如果你的頭文件前加了 <sys/*>,那說明這是系統調用函數頭文件,其在/usr/include/sys下面。

  • 函數都是獲取文件(普通文件,目錄,管道,socket,字符,塊)的屬性。

  • 位置:我的頭文件位置在usr/include/sys/下面;若找不到,可能在:/usr/include/x86_64-linux-gnu/sys/下面
    stat.h的位置

  • PS:(因爲編輯器問題,將一對尖括號改成了一對書名號來顯示)

QString與char等類型的轉換

  • QString與char等類型的轉換23
  1. QString 轉換成 char * 24
 明智做法:【QString轉換爲QByteArray  與  QByteArray 與 char* 的轉換】
      QString Qstr = "Test";
      char *chStr = NULL;
      QByteArray ba = str.toLatin1();或者str.toAscii();
   	  chStr = (char *)malloc(ba.length() + 1);
      memset(chStr, 0, ba.length());//將數組初始化
      memcpy(chStr, ba.data(), ba.length());
      chStr[ba.length()] = '\0';
 直接做法:
      QString str="abc";
      char *ch; 
      QByteArray ba = str.toLatin1();
      ch = ba.data();
  1. char * 轉換成 QString:
     char *c_str = "123456789";
     QString string = QString(QLatin1String(c_str));
  1. QString 轉換成 char [] 或 char [] 轉換成 QString25
   char path[50];
   QString str = "D:\\搜狗\\weka-3jre-x64.exe";
   QByteArray ba = str.toLocal8Bit();
   memcpy(path,ba.data(),ba.size()+1);//加1是爲了最後的終結符,否則轉換回來的時候不知道什麼時候截止
   或者
   char path2[50];
   QString str2;
   str2 = QString::fromLocal8Bit(path2);
   【若用str2 = path2時,運行正常,反而用上一行,出異常了,可能環境不同導致】
  1. char * 轉換成 char [] 或 char [] 轉換成 char * 26
	char * b;
	char buf[100];
    strcpy(buf,b);//一般用於char *  轉換成 char []
    strcpy(b,buf);//雖然不報異常,但char [] 轉換成 char   * 一般是下面這樣的:

	b=buf;//是不是很簡單,b是字符指針,只需存buf變量的指針便可完成轉換

	也可以:
	memcpy(buf,b,100);
  1. char 轉換成 QString:
   char a='b'; 
   QString str; 
   str=QString(a);
  1. QByteArray 轉換成 char *:
   char *ch;//不要定義成ch[n]; 
   QByteArray byte;
   ch = byte.data();
  1. char * 轉換成 QByteArray:
   char *ch; 
   QByteArray byte; 
   byte = QByteArray(ch);
  1. QString 轉換成 QChar(一般要數組來存哦):
     QString str = "123cycy";
     QChar *b = new QChar[7];//b[0]~b[6]就能讀取相對應的字符
     b = str.data();
  1. QChar 轉換成 QString:
    直接使用 QString(QChar ch)即可
    或者QString::append(QChar ch)也行
  1. QChar 轉換成 char:
    char ch;
    QChar Qch;
    ch = QCh.toLatin1();或QChar::toAscii ();
  1. char 轉換成 QChar:
    QChar(char ch) /QChar(uchar ch)
  1. QString 轉換成 數字27
    QString::toXXX 系類函數
    如:
    QString a="120";
    int b; 
    b=a.toInt();
  1. 數字 轉換成 QString:
    QString::number()
    setNum()
    如:
    int a=10; 
    QString b; 
    b=QString::number(a);
  1. QByteArray和十六進制的QString(char)相互轉換*

  2. QString 轉換成 QByteArray:

    QByteArray byte; 
    QString string; 
    byte = string.toAscii();
  1. QByteArray 轉換成 QString:
    QByteArray byte; 
    QString string; 
    string = QString(byte);
  1. QString 轉換成 string:
    QString.toStdString(); 
    string --> QString QString::fromStdString(string);
  1. QDateTime 轉換成 QString :
     QString strBuffer;   
     QDateTime time;    
     time = QDateTime::currentDateTime();    
     strBuffer = time.toString("yyyy-MM-dd hh:mm:ss");    
     // strBuffer = 2015-12-21 17:35:00  
  1. QDateTime 轉換成 QString :
     QString strBuffer;   
     QDateTime time;    
     strBuffer = "2010-07-02 17:35:00";   
     time = QDateTime::fromString(strBuffer, "yyyy-MM-dd hh:mm:ss");

[---------------從這開始,是C++時的轉換------------]

  1. string 轉換成 char * 28
     std::string str="兩袖清風";
     //Tips:c_str()函數是把string 轉換爲const char*類型
     const char* cStr = str.c_str();
     qDebug()<<cStr<<endl;
  1. char * 轉換成 string :
     char* cStr ="兩袖清風";
     std::string str(cStr);
     qDebug()<<str.c_str()<<endl;
  1. unsigned char 轉換成 char 29
     
  1. char 轉換成 unsigned char :
     
  1. int 轉換成 char * :
     
  1. char * 轉換成 int :
     
  1. int 轉換成 char[]:
//我使用了union

  1. char[] 轉換成 int :
     
  1. char 轉換成 int30

  1. int轉換成 char:

char ** 與char *

  • char ** 與char *26
  • char *a [ ];
    • 解釋:由於[ ] 的優先級高於* 所以a先和 [ ]結合,但它還是個數組,數組中的元素纔是char *,即類型爲char *,表示保存地址的指針變量值。
    • 如:char *a[ ] = {“China”,“French”,“America”,“German”};sizeof(a) = 16;
    • 解釋:字符串常量的本質是地址,a 數組中的元素爲char * 指針,指針變量佔四個字節,那麼四個元素就是16個字節了;另外元素保存的是不連續的內存地址。
  • char **s;
    • char **爲二級指針, s保存一級指針 char *的地址。
    • 二級指針保存的是一級指針的地址,它的類型是指針變量,而一級指針保存的是指向數據所在的內存的單元的地址,雖然都是地址,但是類型是不一樣的。

memset(…,…,…)

  • memset(…,…,…)27
  • 原型:void memset(void * s,int c,size_t n);——s的n長度都爲c值【# include <string.h>】
  • 舉例:char a[100];memset(a, '\0’或0, sizeof(a));
  • 功能:是初始化函數(主要初始化某個內存空間),將指針變量 s 所指向的前 n 字節的內存單元用一個“整數” c 替換,注意 c 是 int 型。s 是 void* 型的指針變量,所以它可以爲任何類型的數據進行初始化。用來對一段內存空間全部設置爲某個字符,一般用在對定義的字符串進行初始化爲‘ ’或‘\0’。
  • 注意:一般使用“0”初始化內存單元,而且通常是給數組或結構體進行初始化。可以給字符串數組賦值爲 ‘\0’ 和 0 ,因爲它倆是等價的,而且字符 ‘\0’ 在內存中就是 0。但在 memset 中初始化爲 0 也具有結束標誌符 ‘\0’ 的作用,所以通常我們就寫“0”。

strcpy(…,…)

  • strcpy(…,…)28
  • 原型:char* strcpy(char* dest, const char* src);——實現src到dest的字符串複製【# include <string.h>】
  • 舉例:char a[100],b[50];strcpy(a,b);——要注意a中的字符串長度(第一個‘\0’之前)是否超過50位,如超過,則會造成b的內存地址溢出。
  • 功能:即string copy(字符串複製)的縮寫;只用於字符串複製,並且它不僅複製字符串內容之外,還會複製字符串的結束符,它遇到’\0’就結束拷貝。
  • 注意:str也可以用用個參數的strncpy(a,b,n)。

與memcpy(…,…,…)的區別

  • 與memcpy(…,…,…)的區別31
memcpy(…)
  • 原型:void *memcpy( void *dest, const void *src, size_t count );——將src複製count長度到dest【# include <string.h>】
  • 舉例:char a[100],b[50]; memcpy(b, a, sizeof(b));——注意如用sizeof(a),會造成b的內存地址溢出。
  • 功能:是內存拷貝函數;提供了內存的複製(主要拷貝源空間的數據到目的空間中),對於需要複製的內容沒有限制,因此用途更廣,可以拿它拷貝任何數據類型的對象,可以指定拷貝的數據長度。
區別
  1. 複製的內容不同。strcpy只能複製字符串,而memcpy可以複製任意內容,例如字符數組、整型、結構體、類等。
  2. 複製的方法不同。strcpy不需要指定長度,它遇到被複制字符的串結束符"\0"才結束,所以容易溢出。memcpy則是根據其第3個參數決定複製的長度。
  3. 用途不同。通常在複製字符串時用strcpy,而需要複製其他類型數據時則一般用memcpy。

strncmp(…,…,…)

  • strncmp(…,…,…)32
  • 原型:int strncmp(const char *str1, const char *str2, size_t n);——比較n個長度的字符,str1比較str2,若大於,返回值是>0的,以此類推。【#include <string.h>】
  • 舉例:
  char str1[15];
  char str2[15];
  int ret;
  strcpy(str1, "abcdef");
  strcpy(str2, "ABCDEF");
  ret = strncmp(str1, str2, 4);
  結果是:str2 小於 str1
  • 功能:str1 – 要進行比較的第一個字符串。str2 – 要進行比較的第二個字符串。n – 要比較的最大字符數。
  • 注意:該函數區分大小寫。
  • 返回值:
    如果返回值 < 0,則表示 str1 小於 str2。
    如果返回值 > 0,則表示 str2 小於 str1。
    如果返回值 = 0,則表示 str1 等於 str2。

與strcmp(…,…,…)的區別

strcmp(…,…,…)
  • 原型:strcmp(const char str1,const char str2);——str1比較str2,若大於,返回值是>0的,以此類推。【#include <string.h>】
  • 舉例:
strcmp(“abcd”,”abcd”)的返回值是 0strcmp(“abcd”,”dcba”)的返回值是 -1strcmp(“dcba”,”abcd”)的返回值是 1
  • 功能:可用於比較兩個字符串常量,或比較數組和字符串常量,不能比較數字等其他形式的參數。
  • 返回值:
    比較兩個字符串
    設這兩個字符串爲str1,str2,
    若str1==str2,則返回零;
    若str1 < str2,則返回負數;
    若str1 > str2,則返回正數。
區別
  • strcmp與strncmp都是用來比較字符串的,區別在於能否比較指定長度字符串。

puts(…,…,…)

與printf(…,…,…),qDebug(),fputs(…,…,…),scanf(…,…,…)的區別

printf(…,…,…)
  • C++時:除了打印字符串,還可以打印相應的值
    • %p、 %s 、%d 、%u 33
qDebug()
fputs(…,…,…)
scanf(…,…,…)
區別
  • 區別34

union

struct

與struct的區別

實例

FIFO例子

  • FIFO例子35

實現方式

  • 實現方式36

與pipe區別37

順手瞭解

I2C(IIC)

論壇

總結


  1. 1字節=多少M位(bit)、字節(byte)、字符、編碼之間的關係比特(位,bit),字節(Byte),字符的區別bit、byte、位、字節、漢字、字符之間的區別字節、字、位、比特,這四者之間的關係是什麼? ↩︎

  2. C++中定義和聲明的區別c++中定義和聲明的區別C語言中變量的聲明和定義 ↩︎

  3. C語言中字符串結束符’\0’ Or C語言中字符串結束符’\0’的討論字符串結尾‘0’和‘\0’的區別 ↩︎

  4. string字符串以’\0’結尾C字符串末尾的’\0’問題 ↩︎

  5. 文件權限定義文件權限文檔mode_t 內核文件權限值 S_IRUGO=S_IRUSR | S_IRGRP | S_IROTH ↩︎

  6. Linux的文件描述符文件系統之文件描述符理解文件描述符Linux文件描述符區別文件描述符(Linux)和文件指針(C語言)C語言—文件描述符 ↩︎

  7. C語言 sizeof函數詳解C語言基礎——sizeof的用法總結sizeof()函數用法彙總sizeof()的用法 Or c++中sizeof()的用法介紹strlen()和 sizeof ()的區別 Or strlen和sizeof的區別與總結Qt中sizeofC語言中sizeof()和strlen()的區別C語言中sizeof()與strlen()函數的使用入門及對比C++中sizeof()、size()、length()、strlen()以及vector容器中size()的區別 Or c/c++中sizeof()、strlen()、length()、size()詳解和區別 ↩︎ ↩︎

  8. C/C++中strlen的用法 ↩︎

  9. 【C語言】運算符與操作符的用法全面彙總(非常有用)操作符和運算符的區別 ↩︎

  10. C 庫函數 - perror()perror strerror使用方法 ↩︎

  11. errno 和perrorperror與errnolinux中errno及perror的應用 ↩︎

  12. read函數與write函數read/write函數【還提到了“文件描述符”】、C++文件操作Read函數Qt二進制文件操作(讀和寫)詳解c/c++ 網絡編程 read,write函數深入理解 ↩︎

  13. gets和fgets函數的區別c語言gets()函數與它的替代者fgets()函數c語言中gets ,getschar 和fgets 的用法及三者之間的差別小朋友學C語言(42):gets和fgetsgets和fgets函數及其區別,C語言gets和fgets函數詳解fgets、gets和scanf的區別、、 ↩︎

  14. EOF宏,C語言EOF宏詳解C語言中EOF什麼意思↩︎

  15. Linux下read和fgets的一些比較關於linux下標準讀入read和fgets和scanf的區別↩︎

  16. write函數的詳解與read函數的詳解 ↩︎

  17. Linux(C/C++)下的文件操作open、fopen與freopenC++ open 打開文件(含打開模式一覽表)【C++中使用的,Qt裏有自己的一套模式一覽表】c/c++ 學習-open 函數C/C++ open函數的阻塞和非阻塞Linux系統函數open和close(02)—open函數的返回值 ↩︎

  18. Linux:非阻塞O_NONBLOCK與O_NDELAY的區別 ↩︎

  19. mkfifo函數使用mkfifo函數linux系統編程之管道(三):命名管道FIFO和mkfifo函數【linux】下的mkfifo 命令 和【C語言】中的mkfifo函數linux mkfifo命令基本用法有名管道因路徑權限,導致創建管道失敗的問題分析有名管道mkfifo、、、 ↩︎

  20. umask 怎樣影響新建文件的權限?umask權限使用Linux umask限制導致php的mkdir 0777無效Linux----centos下的umask詳解(翻譯) ↩︎

  21. linux系統文件訪問權限授予Linux使用:文件或目錄的權限設置Linux文件權限 ↩︎

  22. linux中#include <sys/stat.h>的位置#include <sys/stat.h>的作用 ↩︎

  23. QString-char 之間的轉化Qt中的對象類型轉換(Qstring 轉換char*有三種方法)QT中 QString 、String與char*三者之間相互轉換*char[],char ,string之間轉換 ↩︎

  24. Qt學習路程(四)QString轉char * 數組QT如何將QlineEdit裏的QString字符串存儲到unsigned char 數組中VC中char* 與 char[] 的區別 ↩︎

  25. 【QT筆記】QString與char數組轉換 ↩︎

  26. char ** 與char * a[ ] 區別深入 理解char * ,char ** ,char a[ ] ,char a[] 的區別char()與(char)的區別**搬磚:char 和char[]的區別*char 和 char[]的區別* ↩︎ ↩︎

  27. memset函數及其用法,C語言memset函數詳解 ↩︎ ↩︎

  28. strcpy函數處理溢出的建議 ↩︎ ↩︎

  29. 深入瞭解計算機系統中:unsigned char和char的思考和實驗【14】unsigned char、char、int之間的轉換unsigned char與char 轉換字符串轉化爲整數/char和unsigned charC語言 如何把一個變量值賦給一個數組。、、、 ↩︎

  30. int轉換char的正確姿勢c++中int與char相互轉換char轉int,int轉char、、 ↩︎

  31. 深入理解strcpy與memcpy的區別strcpy、memcpy和memset之間的區別【主要是"strcpy與memcpy的區別"】、memset ,memcpy 和strcpy 的根本區別?【也講了memset()函數】 ↩︎

  32. C 庫函數 - strncmp()strcmp與strncmp的區別strncmp–百度百科 ↩︎

  33. C_printf中的%p的實質C/C++ %s %d %u 基本概念與用法 ↩︎

  34. puts和printf更深層次的區別(同一參數,卻得出了不同的結果)scanf、printf、gets、puts的應用及區別C語言scanf()和gets()及printf()和puts()的區別、、、、 ↩︎

  35. 命名管道FIFO使用FIFO來進行兩個進程間的通信《Linux 進程間通信》命名管道:FIFOLinux下循環緩存區(fifo)的實現linux有名管道fifo,進程間通信Linux-進程間通信(二): FIFOLinux系統編程——進程間通信:命名管道(FIFO)、、、、、、 ↩︎

  36. FIFO的數組實現方式C語言循環數組做FIFO隊列–一些認識、、、 ↩︎

  37. fifo與pipe總結linux系統編程之管道(一):匿名管道和pipe函數linux系統編程之管道(二):管道讀寫規則和Pipe Capacity、PIPE_BUF ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章