C语言复习指南

本文深入介绍了C语言中的存储类,包括auto、register、static和extern,以及它们对变量生命周期和作用域的影响。此外,还详细阐述了指针的概念,如取地址、多重指针和函数指针,并通过实例展示了如何使用函数指针。接着,讨论了结构体的定义、初始化、访问成员和指针操作。文章还提到了位域、共用体和枚举等高级特性,帮助读者全面理解C语言的复杂性。
摘要由CSDN通过智能技术生成

简单内容跳过不介绍:基本语法、数据类型相关

C语言

C 语言是一种通用的高级语言,UNIX 操作系统,C编译器,和几乎所有的 UNIX 应用程序都是用 C 语言编写的。由于各种原因,C 语言现在已经成为一种广泛使用的专业语言。
C 语言最初是用于系统开发工作,特别是组成操作系统的程序。由于 C 语言所产生的代码运行速度与汇编语言编写的代码运行速度几乎一样,所以采用 C 语言作为系统开发语言。

优点

  • 易于学习。
  • 结构化语言。
  • 它产生高效率的程序。
  • 它可以处理底层的活动。
  • 它可以在多种计算机平台上编译。

C 存储类

存储类定义 C 程序中变量/函数的的存储位置、生命周期和作用域,这些说明符放置在它们所修饰的类型之前。
不常用:

  • auto:所有局部变量默认的存储类,定义在函数中的变量默认为 auto 存储类,这意味着它们在函数开始时被创建,在函数结束时被销毁。
  • register:这个关键字命令编译器尽可能的将变量存在 CPU 内部寄存器中而不是通过内存寻址访问以提高效率
  • volatile:表明某个变量的值可能在外部被改变,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份,常用多线程

常用:

  • const: 定义的变量的值是不允许改变的,即不允许给它重新赋值
  • static: 静态,修饰全局变量和局部变量
#include <stdio.h>

/* 函数声明 */
void func1(void);
 
static int count = 10;        /* 全局变量 - static 是默认的 */
 
int main() {
  while (count--) {
      func1();
  }
  return 0;
}
 
void func1(void) {
/* 'thingy' 是 'func1' 的局部变量 - 只初始化一次
 * 每次调用函数 'func1' 'thingy' 值不会被重置。
 */                
  static int thingy = 5;
  thingy++;
  printf(" thingy 为 %d , count 为 %d\n", thingy, count);
}
  • extern

extern关键字的使用一:同个文件内

#include <stdio.h>
 
// 函数外定义变量 x 和 y
int x;
int y;
int addtwonum() {
    // 函数内声明变量 x 和 y 为外部变量
    extern int x;
    extern int y;
    // 给外部变量(全局变量)x 和 y 赋值
    x = 1;
    y = 2;
    return x+y;
}
 
int main() {
    int result;
    // 调用函数 addtwonum
    result = addtwonum();
    // result = 3
    printf("result 为: %d",result);
    return 0;
}

extern关键字的使用二:一个源文件中引用另外一个源文件中定义的变量

#include <stdio.h>
/*外部变量声明*/
extern int x ;
extern int y ;
int addtwonum() {
    return x+y;
}
#include <stdio.h>
/*定义两个全局变量*/
int x=1;
int y=2;
int addtwonum();
int main(void) {
    int result;
    result = addtwonum();
    printf("result 为: %d\n",result);
    return 0;
}

C语言指针

  • *取值符号
  • &取地址符号

在这里插入图片描述

  • 多重指针
    在这里插入图片描述
    在这里插入图片描述

函数指针

函数指针是指向函数的指针变量

#include <stdio.h>

// 定义一个函数
int max(int x, int y) {
    return x > y ? x : y;
}
 
// main函数
int main(void) {
    // p 是函数指针,指向max函数
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("请输入三个数字:");
    scanf("%d %d %d", & a, & b, & c);
 
    // 与直接调用函数等价,d = max(max(a, b), c)
    d = p(p(a, b), c); 
    printf("最大的数字是: %d\n", d);
 
    return 0;
}

回调函数

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

#include <stdlib.h>  
#include <stdio.h>

// getNextValue函数作为参数传进去
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void)) {
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
 
// 获取随机值
int getNextRandomValue(void) {
    return rand();
}
 
int main(void) {
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

结构体🌟

  • 定义结构
  • tag 是结构体标签
  • member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义
  • variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量
  • 在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个
struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list ;
  • 结构体变量的初始化
// 定义结构体,结构变量,并赋值
struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};

// 也可以使用时再初始化
struct Books book = {"C 语言", "RUNOOB", "编程语言", 123456};

// 通过点语法访问成员
book.title
  • 指向结构的指针
// 定义指向结构的指针
struct Books *struct_book;
// 指针变量中存储结构变量的地址
struct_book = &book;
// 使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符
struct_book->title;

结构体直接作为参数

  • 内部修改book的成员变量,不影响外部
  • 函数内部操作的是结构体的副本而不是原始结构体本身
printBook(book);

void printBook(struct Books book) {
   printf( "Book title : %s\n", book.title);
   printf( "Book author : %s\n", book.author);
   printf( "Book subject : %s\n", book.subject);
   printf( "Book book_id : %d\n", book.book_id);
}

结构体指针作为参数

  • 内部修改book的成员变量,影响外部
printBook(&book);

void printBook( struct Books *book ) {
   printf( "Book title : %s\n", book->title);
   printf( "Book author : %s\n", book->author);
   printf( "Book subject : %s\n", book->subject);
   printf( "Book book_id : %d\n", book->book_id);
}

位域

  • 位域 bit fields 是一种用于定义结构体成员的特殊技术。它允许我们将一个或多个字段(成员)声明为占用特定位数的数据
  • 位域的主要目的是在结构体中有效地利用内存空间,特别是当我们需要存储大量的布尔值或具有限定取值范围的整数时
struct Date {
    unsigned int day : 5;    // 5位用于表示天数(范围:1-31)
    unsigned int month : 4;  // 4位用于表示月份(范围:1-12)
    unsigned int year : 12;  // 12位用于表示年份(范围:0-4095)
};

共用体

  • 类似结构体的数据类型,它允许在相同的内存位置存储不同的数据类型。
  • 共用体的目的是节省内存,因为它们在任意时刻只能容纳一个成员的值。
#include <stdio.h>
#include <string.h>
// 定义共用体
union Data {
   int i;
   float f;
   char  str[20];
};
 
int main( ) {
   union Data data;        
   data.i = 10;
   data.f = 220.5;
   strcpy( data.str, "C Programming");
 
   printf( "data.i : %d\n", data.i);
   printf( "data.f : %f\n", data.f);
   printf( "data.str : %s\n", data.str);
 
   return 0;
}

// 最后只有最后一个数值能正常输出
// data.i : 1917853763
// data.f : 4122360580327794860452759994368.000000
// data.str : C Programming

枚举

enum DAY {
	MON=1, TUE, WED, THU, FRI, SAT, SUN
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值