拾遗:Unix/Linux C_01

时间:2022-04-07 23:44:27
1 alias cc='cc -D_POSIX_C_SOURCE=200809L -g -ansi -std=c99 -Wall -Wextra'
2 alias gcc='gcc -D_POSIX_C_SOURCE=200809L -ansi -std=c99 -Wall -Wextra -O2 -march=haswell'
  • restrict: C语言中的一种类型限定符 (Type Qualifiers), 用于告诉编译器, 对象已经被指针所引用, 不能通过除该指针外所有其他直接或间接的方式修改该对象的内容
  • register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 '&' 运算符(因为它没有内存位置);寄存器只用于需要快速访问的变量,比如计数器;还应注意的是,定义 'register' 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制;
  • static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁;因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值;当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内; 
  • extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候; 
  • 当局部变量被定义时,系统不会对其初始化,您必须自行对其初始化;定义全局变量时,系统会自动对其初始化; 
  • typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的;
    • int getchar(void)   函数从屏幕读取下一个可用的字符,并把它返回为一个整数;
      FILE *fopen( const char * filename, const char * mode );
      int fclose( FILE *fp );
      int fputc( int c, FILE *fp );
      int fputs( const char *s, FILE *fp );
      int fprintf(FILE *fp,const char *format, ...) 
      int fgetc( FILE * fp );
      char *fgets( char *buf, int n, FILE *fp );
      fgets() 从 fp 所指向的输入流中读取 n - 1 个字符;它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 \0 字符来终止字符串; int fscanf(FILE *fp, const char *format, ...) 函数来从文件中读取字符串,但是在遇到第一个空格字符时,它会停止读取;
      在读取字符串时,只要遇到一个空格,scanf() 就会停止读取,所以 "this is test" 对 scanf() 来说是三个字符串;
  • 下面两个函数用于二进制输入和输出:
    • size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);
      size_t fwrite(const void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);
      这两个函数都是用于存储块的读写 - 通常是数组或结构体;
  •  C 预处理器(C Preprocessor)简写为 CPP;下面列出了一些重要的预处理器指令:
    • #define  定义宏
    • #include  包含一个源代码文件
    • #undef  取消已定义的宏
    • #ifdef  如果宏已经定义,则返回真
    • #ifndef  如果宏没有定义,则返回真
    • #if  如果给定条件为真,则编译下面代码
    • #elif  /*可选*/  如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码
    • #endif  结束一个 #if……#else 条件编译块
  • 预定义宏:ANSI C 定义了许多宏;在编程中可以使用这些宏,但是不能修改这些预定义的宏;预处理器 defined 运算符是用在常量表达式中的,用来确定一个标识符是否已经使用 #define 定义过;如果指定的标识符已定义,则值为真(非零),否则为假(零);
    • __DATE__  程序编译时的日期,一个以 "MMM DD YYYY" 格式表示的字符常量;
    • __TIME__  程序编译时的时间,一个以 "HH:MM:SS" 格式表示的字符常量
    • __FILE__  这会包含当前文件名,一个字符串常量
    • __LINE__  这会包含当前行号,一个十进制常量
  • C 语言提供了 perror() 和 strerror() 函数来显示与 errno 相关的文本消息;通常情况下,程序成功执行完一个操作正常退出的时候会带有值 EXIT_SUCCESS;在这里,EXIT_SUCCESS 是宏,它被定义为 0;如果程序中存在错误情况,退出程序时,会带有状态值 EXIT_FAILURE,被定义为 -1;
    • perror() 函数显示您传给它的字符串,后跟一个冒号、一个空格和当前 errno 值的文本表示形式;
    • strerror() 函数,返回一个指针,指针指向当前 errno 值的文本表示形式;
  • 可变参数函数:需要使用 stdarg.h 头文件,该文件提供了实现可变参数功能的函数和宏;具体步骤如下:
    • 定义一个函数,最后一个参数为省略号,倒数第二个参数(省略号前面的那个参数)是 int类型的,表示参数的个数;在此之前的位置仍然可以定义常规参数;
    • 在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的;
    • 使用函数的 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表;
    • 使用 va_arg 宏和 va_list 变量顺序访问参数列表中的每个项;
    • 使用宏 va_end 来清理赋予 va_list 变量的内存;
      • include <stdarg.h>
        void func(char other, int num, ...)
        {
            va_list test;
            va_start(test, num);
            va_arg(test, type);  /* type指可变参数的数据类型,与左值保持一致 */
            va_end(test);
        }
  • 动态分配内存函数;
    • void *calloc(int n, int size);  分配一个包含 n 个元素的数组对象,每个元素的大小为 size 字节;并把所有元素初始化为0;
    • void *malloc(int n);   返回一个指向 n 字节内存空间的指针对象,不对分配的内存进行初始化,效率较高;
    • void *realloc(void *address, int newsize);   重新分配内存,把内存扩展到 newsize,若第一个参数为NULL,与malloc效果相同;
    • void free(void *address);   释放 address 所指向的内存块;
  • 在 C 语言中,字符串实际上是使用 null 字符 '\0' 终止的一维字符数组;
    • strcpy(s1, s2);  复制字符串 s2 到字符串 s1;
    • strcat(s1, s2);  连接字符串 s2 到字符串 s1 的末尾;
    • strlen(s1);  返回字符串 s1 的长度;不包含末尾的NULL字符;
    • strcmp(s1, s2);  如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0;按ansi编码比较;
    • strchr(s1, ch);  字符查找函数,返回一个指针,指向字符 ch 在字符串 s1 中首次出现的位置;
    • strstr(s1, s2);  字符串查找函数,返回一个指针,指向字符串 s2 在字符串 s1 中首次出现的位置;