C语言学习笔记十、 五种修饰函数的类型,typedef函数,宏定义,编译的过程,条件编译

十、 五种修饰函数的类型,typedef函数,宏定义,编译的过程,条件编译

 

1. const --》只读指针

1.修饰基本数据类型变量:  const int a = 10;    //修饰的变量必须初始化
                                           //表示a为只读变量,不能修改
                                           //a = 100; 编译会报错!!!
2.修饰指针变量:
第一种情况:
int a=10, b =200;
int * const p = &a;     //必须初始化
p = &b;                 //编译会报错
*p = 300;               //p指针解引用是可以的
​
第二种情况:
int a=10, b =200;
int const * p = &a;     //必须初始化
p = &b;                 //可以
*p = 300;               //p指针解引用编译会报错
​
第三种情况:
int a=10, b =200;
const int * p = &a;     //必须初始化
p = &b;                 //编译会报错
*p = 300;               //p指针解引用是可以的
​
第四种情况:
int a=10, b =200;
const int * const p = &a;     //必须初始化
p = &b;                       //编译会报错
*p = 300;                     //p指针解引用编译会报错

2.volatile -->防止编译器优化变量

//单片机延时函数
void delay()
{
    int i = 0x1000000;          //可能会在编译时被编译器优化(删除)掉
​
    while(i--);
}
    
​
​
    //单片机延时函数
    void delay()
    {
        volatile int i = 0x1000000; //编译器不会优化变量
        
        while(i--);
    }

3.auto和register

1、auto自动化变量(内存变量),定义变量时可以省略不写
        int a; <==> auto int a; 
​
2、register(寄存器变量) --》用在调用频繁的变量可以定义成一个寄存器变量
        register int a; --》变量定义时分配的寄存器存储
​
注意:
    1》定义寄存器变量是不一定成功(主要看编译器),如果不成功他会自动定义成自动化变量
    2》寄存器变量没有内存地址

4.extern

1、概念:表示外部调用,从其他.c文件里面调用
2、使用方法: 
1》修饰变量
    extern int a; -->从其他文件调用这个变量,如果其他.c文件没有定义肯定会报错
2》修饰函数
    extern int add(int a, int b); -->表示当前.c没有定义该函数,在其他.c里面定义了该函数,如果其他.c文件没有定义肯定会报错
    
注意:static修饰的变量或函数,都是只能用于当前这个.c; 该变量不能再被estern调用!!!

5.typedef --》给数据类型取别名

1、给基本数据类型取别名
    typedef int INT;  //给int取了一个别名叫INT
    int a; 《===》 INT a; 
​
2、给数组数据类型取别名
    typedef int ARRAY[4];   //给数组类型为:int ()[4]取了一个别名叫做 ARRAY
​
3、给函数指针数据类型取别名
    int add(int , int );  ---》对应的函数指针类型为:int (*)(int , int );
    typedef int (*FUNC_P)(int , int ); 
                                //给函数指针int (*)(int , int )取别名叫FUNC_P
​
4》给结构体数据类型取别名
(1) 给结构体类型 struct student取了一个别名叫做STU,所以 struct student 《==》STU
1>
struct student
{
            char name[15];
            int num;
            int age;
            char sex;
}STU; 定义了一个结构体数据类型变量叫做STU
​
2>
typedef struct student
{
            char name[15];
            int num;
            int age;
            char sex;
}STU;       //给结构体数据类型struct student 取了一个别名叫做 STU
​
struct student lisi; ==》STU lisi;  //都是表示定义结构体变量
struct student *p; ==》STU *p;  //表示定义结构体指针
​
3>
typedef struct student
{
            char name[15];
            int num;
            int age;
            char sex;
}STU, *STU_P;   //给结构体数据类型struct student 取了一个别名叫做 STU
                //给结构体数据类型struct student *(结构体指针)取了一个别名叫做 STU_P
struct student lisi; ==》STU lisi;  //都是表示定义结构体变量
struct student *p; ==》STU *p;  //表示定义结构体指针
struct student *p; ==》  STU_P  p; //表示定义结构体指针

6.宏定义(又称之为宏替换,在代码编译阶段中的预处理阶段进行替换,不是在程序运行的过程中替换)

1.宏定义变量
#include <stdio.h>
#include <string.h>
​
#define MUN  20
#define LCD_W 800
#define LCD_H 480
​
int main(int argc, const char**argv)
{
    int arry[MUN];
    printf("%d\n", sizeof(arry));
    int lcd_len = LCD_H*LCD_W;
    printf("%d\n", lcd_len);
    
    return 0;
}
注意:1》宏定义它是不需要分配内存
     2》宏替换不能替换字符串里面的字符  
​
2.带参宏 --》也是在编译阶段中的预处理阶段进行处理替换,它是和函数不同
​
带参宏与带参函数的5个区别:
                    带参宏             带参函数
处理时间             编译时               运行时
参数类型               无                需定义
程序长度              变长                不变
占用存储空间           否                  是
运行时间           不占运行时间         调用和返回时占

7.编译的过程

把.c文件编译生成一个可执行文件,其实他是分为4个步骤:预处理、编译、汇编、链接
命令:gcc hello.c -o hello
1>预处理
    预处理的编译命令:
    gcc -E hello.c -o hello.i
    作用:
        (1)删除了注释代码
        (2)展开了头文件
        (3)处理了宏定义、带参宏、条件编译
    
2>编译
    编译的编译命令:
    gcc -S hello.i -o hello.s 
    作用:
        (1)把C语言翻译成汇编语言
        (2)检查代码语法错误
​
3>汇编
    汇编的编译命令:
    gcc -c hello.s -o hello.o 
    作用:
        (1)把汇编语言翻译成机器码(二进制)
​
4>链接
    编译命令:
    gcc hello.o -o hello
    作用:
        链接要用到的函数库,把函数库的静态库编译到可执行文件里面,动态库在你要执行时再调用

8.条件编译

条件编译--》有选择的编译,一般用于代码调试,也是在编译阶段中的预处理阶段进行处理
命令:gcc test5.c -o test5 -DNUM   -->-D 表示定义宏,例如:-DNUM表示定义宏NUM!!!
​
1》
#ifndef  -->if not define ,如果没有定义某个宏,就会把代码编译到可执行文件
#ifndef NUM
        
    //代码块
        
#endif
​
2》
#ifdef  -->if define ,如果定义了宏,就会把代码编译到可执行文件
#ifdef  NUM
        
    //代码块
​
#endif  
​
3》
#if 如果为真就会把代码编译到可执行文件
#if 1
​
    printf("hello world\n");
    
#else
    
    printf("good boy\n");
    
#endif
​
#include <stdio.h>
​
/***********************************************************************************/
关于程序拆分 --》即把一个复杂的.c文件拆分为多个.c / .h文件
例子:         将project.c文件拆分为project.c、add.c和add.h三个文件。
//函数声明
int add(int a, int b);
int reduce(int a, int b);
​
int main(int argc, const char**argv)
{
    int num = add(100, 200);
    printf("%d\n", num);
    int num1 = reduce(300, 100);
    printf("%d\n", num1);
    return 0;
}
​
int add(int a, int b)
{
    return a+b;
}
    
拆分效果:
​
gec@ubuntu:/mnt/hgfs/C语言/11/code/test/test$ cat project.c -n
1   #include <stdio.h>
2   
3   //函数声明
4   extern int add(int a, int b);
5   int reduce(int a, int b);
6   
7   int main(int argc, const char**argv)
8   {
9       
10      int num = add(100, 200);
11      printf("%d\n", num);
12      
13      int num1 = reduce(300, 100);
14      printf("%d\n", num1);
15      
16      return 0;
17  }
    
gec@ubuntu:/mnt/hgfs/C语言/11/code/test/test$ cat add.c -n
1   #include "add.h"
2   
3   
4   int add(int a, int b)
5   {
6       return a+b;
7   }
     
     
gec@ubuntu:/mnt/hgfs/C语言/11/code/test/test$ cat add.h -n
1   #ifndef  __ADD_H__
2   #define  __ADD_H__
3   
4   //要包含的头文件
5   #include <stdio.h>
6   
7   //宏定义
8   
9   //结构体数据类型
10  
11  //全局变量
12  
13  
14  
15  
16  //函数声明
17  int add(int a, int b);
18  
19  
20  #endif
     
编译命令: gcc project.c add.c -o project  注意:编译的时候要注意加上所有你需要运行的文件名!!!
执行文件:./project
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值