管道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 ↩︎

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