C语言的一些知识点(一)
  • 为什么计算机使用补码存储数据?
    1. 避免了0的编码有两个的问题
    2. 符号位和数据位可以一起处理,减法可以通过加法实现
  • 判断大小端字节序
    int main(void)
    {
    int a= 0x12345678;
    char b = a;
    if(b == 0x78)
    {
        printf("little endian\n");
    }
    else
    {
        printf("big endian\n");
    }
    }
  • extern关键字
    //同一个.c文件中
    extern int c;
    //此处变量c不开辟空间
  • static关键字
    //file1.c
    static int  x = 10;
    //file2.c
    extern int x;
    //错误。无法引用。static将x的生命周期限定在file1.c中
  • sizeof() 是运算符。
  • 数据类型转换规则:char -> short -> int -> long -> float -> double。
  • break关键字用于结束整个循环,在嵌套循环里结束本层的循环。
    continue关键字结束本次的循环。
  • 短路求值问题:
    • 与 -> 第一个条件为false,后面不执行;
    • 或 -> 第一个条件为true,后面不执行。
  • 数组给另一个数组赋值时最好一个元素一个元素的赋值。(可以直接拷贝)
  • 字符串别忘记了结尾的'\0'
  • 全局变量默认为0
  • 变量命名规则:
    1. 由字母、数字、下划线组成;
    2. 不能是关键字,如:for、int等
    3. 不能以数字开头;
    4. 区分大小写。
  • putchar('a'); //输出不自动换行
  • puts("hello");//输出自动换行
  • 字符串输入:char a[5];scanf("%s", a);//遇见空格或换行就结束了 gets(a); //可以输入空格,换行结束
  • 二维数组可以省略行数,但不能省略列数。
  • 使用函数的好处:
    • 便于更新和维护;
    • 方便阅读;
    • 便于分工合作开发。
  • 指针:
    1. 两个指针不能加法;
    2. 野指针:未指向有效地址的指针,如int *p;
    3. 空指针: int *p = NULL;
  • int *p[3] 为整型指针数组 ([]优先级高于*)
  • int (*p)[3] 为数组指针,p指向int[3]类型的指针,通常将二维数组赋值给p
    int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    int (*p)[4] = a;
    int i, j;
    for(i = 0; i < 3; i++)
    {
        for(j = 0; j < 4; j++)
        {
            printf("%02d\n", p[i][j]);
            //p[i][j] <=> *(*(p + i) + j)
        }
    }
    char *s[5] = {"hello", "world", "c", "linux", "jeffrey"};
    for(i = 0; i < 5; i++)
    {
        printf("%s\n", s[i]);
    }
  • gcc编译流程
    预处理 -> 编译 -> 汇编 -> 链接

    1. 预处理:头文件展开、注释处理、宏替换
      gcc -E -o hello.i hello.c
    2. 编译:将C程序编译成汇编程序,检查语法错误
      gcc -S -o hello.s hello.c
    3. 汇编:将C程序编译成机器码源程序
      gcc -c -o hello.o hello.c
    4. 链接:将多个.o文件和库文件等链接到一起
      gcc -o hello hello.c
  • Makefile文件编写

    EXEC = main
    OBJS += main.o
    OBJS += add.o sub.o mul.o div.o
    CC = gcc
    AR = ar
    
    $(EXEC) : $(OBJS)
        $CC -o $@ %^
    .o : .c
        $CC -c $<
    clean:
        rm $(EXEC) $(OBJS)

    $@ 目标的完整名称
    $^ 所有依赖文件
    $< 第一个依赖文件

  • 函数指针
    int add(int a, int b)
    {
        return a + b;
    }
    int sub(int a, int b)
    {
        return a - b;
    }
    int mul(int a, int b)
    {
        return a * b;
    }
    int div(int a, int b)
    {
        return a / b;
    }
    int process(int (*p)(int, int), int a, int b)
    {
        return p(a, b);
    }
    int main()
    {
        printf("sum is %d\n", process(add, 5 , 3));
        printf("sub is %d\n", process(sub, 5 , 3));
        printf("mul is %d\n", process(mul, 5 , 3));
        printf("div is %d\n", process(div, 6 , 3));
        int(*p[4])(int, int) = {add, sub, mul, div};
        int i = 0;
        for(i = 0; i < 4; i++)
        {
            printf("value is %d\n", p[i](4, 2));
        }
        return 0;
    }
  • 函数参数传递:
    1. 值传递:通常不能改变实参的值;
    2. 地址传递:可以改变实参的值;
  • 指针类型大小
    int p; char q;
类型 32位 64位
sizeof(p) int * 4 8
sizeof(*p) int 4 4
sizeof(q) char * 4 8
sizeof(*q) char 1 1
  • 结构体:将描述同一事物的变量组织到一起
    struct student
    {
        char name[10];
        int number;
        int age;
        int score;
    };
    struct student s = {"jeffrey", 1001, 25, 99};
    printf("my name is %s, my number is %d, my age is %d, my score is %d\n", s.name, s.number, s.age, s.score);
    //更改时只能对成员更改,不能整体修改;
    //错误修改name成员 s.name = "hello";
    //正确的修改name 成员
    strcpy(s.name, "xiaowang");
    //错误的示例
    struct student s;
    s = {"xiaowang", 1001, 26, 98};
    //除了初始化时,其他时候不可以整体赋值;
    //错误的示例
  • 内存分配:
    1. 静态分配:在编译时分配好空间,如int a[10];
    2. 动态分配:在运行时再确定内存大小,如malloc(100);
      动态分配的内存不会自动释放,需要使用free函数释放,如:void *p = malloc(200); if(p) free(p);
      动态分配可能会失败,失败会返回NULL,所以使用malloc后记得判空。
  • 按位左移,左移一位,结果乘2
  • 按位右移,右移一位,结果÷ 2
  • static关键字:
    static int number;  //全局变量,在本文件中有效
    static int func()   //函数只能在本文件中被访问
    {
        static int x;   //变量生命周期延长,默认值为0
    }
  • a.c中有定义全局变量int x,则想要b.c中使用x,需要extern int x;
  • const关键字:
    const int a = 10;   //a为常量,不能修改;
    int const *p; //修饰*p,*p为常量,不能修改;
    int * const p; //修饰p, p为常量,不能修改;
    int const * const p; //修饰*p和p,均为常量,不能修改。
  • 内存分为:全局区、栈区、堆区、代码区
    #include <stdio.h>
    int x;  //全局区
    int main()
    {
        int y;  //栈区
        static int z;   //全局区
        int *p = malloc(24);    //malloc的内存在堆区,p在栈区
        char *p = "hello";    //hello在代码区,q在栈区
    }
  • 库文件:
    1. 动态库:运行时再加载;
    2. 静态库:在编译时,将静态库打包至可执行文件中。
      win中动态库:.dll文件,静态库.lib文件;Linux中动态库.so,静态库.a.
  • 动态库和静态库对比:
    1. 链接时间:动态库在程序运行时被加载;静态库则是在编译时被链接到目标代码中,运行时不在需要该库;
    2. 执行速度:静态库链接的程序略快于动态库链接的程序;
    3. 内存大小:动态库更节省内存。
      IP签名

评论

  1. 博主
    Windows Chrome 118.0.0.0
    2 年前
    2023-11-02 20:28:12

    你好啊

    • 博主
      jeffrey
      Windows Chrome 118.0.0.0
      2 年前
      2023-11-02 20:28:24

      你好你好

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
error: Content is protected !!内容保护!!