1·局部变量和全局变量
局部变量位于栈区,全局变量位于全局区
1.1局部作用域与全局作用域
变量在空间上分有局部作用域与全局作用域
局部作用域:
在函数内部声明的变量具有局部作用域,它们只能在函数内部访问,在函数调用结束以后立刻释放
全局作用域:
在函数外部定义的变量,一直占用内存空间,比较耗费内存。
1.2变量的生存期
变量从时间方面静态生存期和动态生存期区别
静态生存期:
只要程序开始运行,这种生存期的变量就被分配了内存,这种变量的生存期和程序的运行期相同.
全局变量和被static修饰的局部变量都是静态生存期。
动态生存期:可理解为局部变量,诞生于声明点,结束于块执行完毕。
1.3auto变量和register变量
auto变量:
这个这个关键字用于声明变量的生存期为自动
register变量:
用register声明的变量是寄存器变量,是存放在CPU的寄存器里的。而我们平时声明的变量是存放在内存中的。
#include <stdio.h>
#include "1_1.h"
int g_i;//位于全局区 拥有静态生存期
void foo(void)
{
static int i = 10;//由static修饰的,位于全局区,拥有静态生存期
++i;
printf("%d\n",i);
}
int main(void)
{
register int k;//被register修饰的不能取地址 &i错误
int i = 10,j = 20;//位于栈区,作用于最近花括号以内
printf("%d\n",add());
printf("%d\n",sub());
foo();
foo();
return 0;
}
2.标识符运用四个要求
3.预处理命令
3.1宏定义
格式:#define 标识符 字符串
掌握"宏"概念的关键是“换”,无脑的将文件中相同的标识符替换为字符串例:
#define PI 3.1415926
把程序中出现的PI全部换成3.1415926
(1)宏名一般用大写
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4)宏定义末尾不加分号;
(5)宏定义通常在文件的最开头。
(6)宏定义可以嵌套
(7)宏定义不分配内存,变量定义分配内存
(8)宏替换只作替换,不做计算,不做表达式求解。
3.2多个文件共同编译
在做项目时,程序员各自完成一个项目的部分编译,将分工完成的文件整合汇编大大提高工作效率。
在Linux操作系统中使用gcc -o app main.c fun.c将main.c文件和fun.c文件汇编在app文件中。
fun.c在头文件fun.h声明所定义的函数,在main.c文件预处理声明fun.h的所在的路径,将可以在主函数调用fun.c所定义的函数。
对于头文件的预处理通常采用#include "XXX.h",表示在Linux中与主调文件的相对路径,如果与主调文件不在同一文件夹,可以采用#include ”/home/.../... "绝对路径调用相关文件
3.3 条件编译
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef 与#ifdef相反,判断某个宏是否未被定义
#endif #if, #ifdef, #ifndef这些条件命令的结束标志
defined 与#if, #elif配合使用,判断某个宏是否被定义
在头文件中常用
#ifndef _大写文件名_
#define _大写文件名_
声明;
声明;
#endif
#ifndef _PRINTCALENDAR_
#define _PRINTCALENDAR_
extern void printCalendar(int year,int month);
#endif
4.项目:某年某月日历显示
#ifndef _PRINTCALENDAR_
#define _PRINTCALENDAR_
extern void printCalendar(int year,int month);
#endif
#include <stdio.h>
#include "printcalendar.h"
int main()
{
printCalendar(2024,2);
return 0;
}
#include <stdio.h>
int isLeapyear(int year)
{
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
int daysOfTheMonth(int year,int month)
{
if(month < 1 || month > 12)
{
return -1;
}
int days[] = {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(month != 2)
{
return days[month - 1];
}
else
{
return isLeapyear(year) ? 29 : 28;
}
}
long daysAfter1900(long year,long month)
{
long j = 0;
for(long i = 1900 ;i < year ;i++)
{
if(isLeapyear(i) != 0)
{
j++;
}
}
// printf("%d\n",j);
long sum = 0;
for(long k = 1;k < month;k++)
{
sum += daysOfTheMonth(year,k);
}
long days;
days = j * 366 + (year - j - 1900) * 365 + sum + 1;
return days;
}
int weekOfTheFirstDay(int year,int month)
{
int week ;
week = daysAfter1900(year,month) % 7;
return week;
}
void printCalendar(int year,int month)
{
int days = daysOfTheMonth(year,month);
int week = weekOfTheFirstDay(year,month);
int len = (7 - (weekOfTheFirstDay(year,month) % 7)) * 4 ;
puts(" 日 一 二 三 四 五 六");
for(int i = 0;i < len; i++ )
{
printf(" ");
}
int k = week;
for(int j = 1;j <= days;j++)
{
k++;
printf("%3d",j);
if(k % 7 == 0)
{
printf("\n");
}
}
}