系统级程序设计笔记(零)

  • 系统级程序设计笔记零
    • 1-概念点
    • 2-KR C与ANSI C
    • 3-gcc与gdb的基本使用方式
      • 1gcc常用参数
      • 2gdb调试方式
    • 4-stdioh
      • 函数原型概览
      • 常数
      • 变量
      • 数据结构
    • 5-重要的c代码片段
    • 4-c语言中的两个问题
      • 1gets与fgets
      • 2返回局部指针的修改方案

系统级程序设计笔记(零)

1-概念点

  • C语言的基本调试环境
  • C语言中关键概念的使用,以及其存在的缺陷
  • 指针与数组概念的关系
  • 数据结构

2-K&R C与ANSI C

  1. K&R C。1978年由Kernighan和Ritchie合写的书《The C Programming Language》,形成了C语言的事实的标准,简称为K&R C。

  2. ANSI C(C89或C90)。1989年,美国国家标准局(ANSI)颁布了第一个官方的C语言标准(X3.159-1989),简称为ANSI C或C89;1990年,它被国际标准化组织(ISO)采纳国际标准(ISO/IEC9899:1990),简称为C90。这个标准是目前广泛使用并完全支持的。

  3. K&R C 与 ANSI C的区别

3-gcc与gdb的基本使用方式

(1)gcc常用参数

  1. 指定别名

    gcc -o hello.c hello.out

  2. 预处理

    gcc -E hello.c -o hello.i

  3. 编译

    gcc -S hello.i hello.s

  4. 汇编

    gcc -c hello.s -o hello.o

  5. 链接

    gcc hello.o -o hello.out

  6. 调试

    gcc -g hello.c -o hello

(2)gdb调试方式

链接:gdb调试命令的使用及总结

4-stdio.h

引用自维基百科:https://zh.wikipedia.org/wiki/Stdio.h

函数原型概览

stdio.h位于/usr/include下。

  1. 文件访问
    fopen
    freopen
    fflush
    fclose
  2. 二进制输入/输出
    fread
    fwrite

  3. 非格式化输入/输出
    fgetc/getc
    fputc/putc
    ungetc
    fgets : 从流中读取n-1个字符或读完一行,参数str用于接收读取的字符串。注意当读取一行时,不包括行尾的’\n’字符。
    fputs

  4. 格式化输入/输出
    scanf/fscanf/sscanf
    printf/fprintf/sprintf
    perror

  5. 文件定位
    ftell
    fseek
    fgetpos
    fsetpos
    rewind

  6. 错误处理
    feof
    ferror

  7. 文件操作
    remove
    rename
    tmpfile 生成一个临时文件
    tmpnam 生成一个唯一的文件名

常数

  • EOF :一个用于指明到达文件尾部,值为负的有符号整形数。
  • NULL:一个由宏展开的空指针常量。或者说,是一个代表在内存中不是合法地址的常量。
  • SEEK_CUR:一个传给函数fseek()的整形参数,要求文件指针以相对于当前位置的偏移量定位。
  • SEEK_END:一个传给函数fseek()的整形参数,要求文件指针以相对于文件尾部的偏移量定位。
  • SEEK_SET:一个传给函数fseek()的整形参数,要求文件指针以相对于文件头部的偏移量定位。

变量

  • stdin:标准输入流指针,负责传递来自标准输入的文字输入流(通常是键盘)。
  • stdout:标准输出流指针,负责传递到标准输出的文字输出流(通常是显示终端)。
  • stderr:标准错误输出流指针,传递来自所有输入输出中返回的错误信息(通常是显示终端)。

数据结构

  • FILE
    一个包含对文件流或文本流执行读入或输出所需信息的结构。其中包括
    一个文件描述符
    当前流的位置
    文件尾部指示
    错误指示
    指向流缓冲区的指针(如果适用)
  • size_t
    sizeof操作符对应的无符号整形数类型。

5-重要的c代码片段

1、赋值操作:在严格的标准下,指向常量的指针不可以被赋值给

char *cp;
const char *ccp;
ccp = cp;
//cp = ccp;

2、const 使用

const int limit = 10;
const int * limitp = &limit;
int i = 27;
limitp = &i;
//limit = 20;

3、 赋值操作失败的原因

foo(const char **p) { }
main(int argc, char **argv)
{
    foo(argv);
}

4、整形提升

int array[] = {233412172049916};
#define TOTALELEMENTS (sizeof(array) / sizeof(array[0])) 
int main()
{
    int d = -1, x;
    /*...*/
    if(d<=TOTAL_ELEMENTS-2)// 应改为d<=int(TOTAL_ELEMENTS-2),因为d转换为unsigned int会变为极大的一个值
        x=array[d+1];
    /*...*/
}

5、 Fall Through:不添加break会导致case2之后依次执行

switch (2) {
    case 1: printf("case 1 \n");
    case 2: printf("case 2 \n");
    case 3: printf("case 3 \n");
    case 4: printf("case 4 \n");
    default: printf("default \n");
}

6、 break的使用:在if中的break会导致外部的switch、while、for等的break

network code()
{
    switch (line)
    { 
        case THING1: 
            doit1(); 
            break; 
        case THING2: 
            if (x == STUFF)
            {
                do_first_stuff();
                if (y== OTHER_STUFF) break;
                do_later_stuff();
            } /' coder meant to break to here...'/
            initialize_modes_pointer(); 
            break;
        default: processing();
    } /' ...but actually broke to here! '/ 
    use_modes_pointer();
    /' leaving the modespointer uninitialized '/
}

7、 staic的使用:static变量只初始化一次

generate_initializer(char * string)
{
    static char separator=’’;
    printf( "%c %s \n", separator, string);
    separator =’,’;
}

4-c语言中的两个问题

(1)gets与fgets

(2)返回局部指针的修改方案

能不能返回局部指针变量,不在于这个指针变量的类型和性质(不在于该指针是不是局部指针变量),而在于该指针指向的对象的类型和性质。如果该指针指向函数内部的栈空间,则程序非法,如果指向静态区域的地址,则合法。

  • 返回指向静态存储区变量的指针
  • 返回指向常量字符串的指针
  • 返回一个指向堆内存的指针

你可能感兴趣的:(系统级程序设计)