目录
- 一、多文件编程
- (一)不写头文件的方方式进行多文件编程
- (二)通过头文件方式进行多文件编程
- (1)方法
- (2)头文件守卫
- (三) 使用多文件编程实现+ - * / 功能
- 二、存储类型
- (一)auto
- (二)register
- (三)const
- 1. const修饰局部变量和全局变量
- 2. const修饰指针
- (四)static
- 1. static修饰的局部变量
- 2. static修饰的全局变量
- 3.static修饰函数
- (五)extern
- (六)volatile
- 三、结构体
- (一)结构体类型定义
- (二)结构体变量的定义
- (三)结构体变量赋值
- 1. 定义结构体变量的同时进行赋值
- 2. 定义结构体类型的同时定义变量并进行赋值
- 3. 在定义结构体变量时对指定成员进行赋值
- 4. 在定义完结构体变量后,通过'.'进行赋值
- (四)结构体成员访问
- (五)结构体内部指针的使用
- (六)结构体指针传参
一、多文件编程
编写一个大型文件时,一般会按照功能生成多个.c文件,
(一)不写头文件的方方式进行多文件编程
extern(存储类型):定义的内容在其他文件中。
类似文件声明,只不过声明的函数在其他文件中。
eg:
function1.c 文件
#include <stdio.h>void function1()
{printf("This is fun1 file\n");
}
function2.c 文件
#include <stdio.h>void function2(int len)
{for(int i=0;i<len;i++){printf("This is fun2 file\n");}
}
test.c 文件
#include <stdio.h>extern void function1(); //function()为定义在其他文件中的函数
extern int function2(int len);int main()
{function1();function2(3);return 0;
}
编译方法:
gcc test.c function1.c function2.c -o test
输出结果:
(二)通过头文件方式进行多文件编程
(1)方法
#include "head1"
- 注:使用引号,是先在自己的路径下找,再去系统的库文件去寻找
编译方法:
gcc test.c function1.c function2.c
或者
gcc *.c
意思是编译所有.c文件
(2)头文件守卫
防止重复导入头文件
head1.h文件
#ifndef __HEAD1_H__
#define __HEAD1_H__/***code***/#endif
(三) 使用多文件编程实现+ - * / 功能
eg:
main.c文件
#include "func.h" int main(int argc, const char *argv[])
{int x,y;char op;printf("please input:");scanf("%d%c%d",&x,&op,&y);switch(op){case '+':printf("%d%c%d=%d\n",x,op,y,add(x,y));break;case '-':printf("%d%c%d=%d\n",x,op,y,sub(x,y));break;case '*':printf("%d%c%d=%d\n",x,op,y,mul(x,y));break;case '/':printf("%d%c%d=%d\n",x,op,y,div(x,y));break;}return 0;
}
func.h文件
#ifndef __FUN_H__
#define __FUN_H__#include <stdio.h>extern int add(int x,int y);
extern int mul(int x,int y);
extern int div(int x,int y);
extern int sub(int x,int y); #endif
add.c 文件
int add(int x,int y){return x+y;}
sub.c 文件
int sub(int x,int y){return x-y;}
mul.c 文件
int mul(int x,int y){return x*y;}
div.c 文件
int div(int x,int y){return x/y;}
输出结果 :
二、存储类型
<存储类型> <数据类型> 标识符 = value;
(一)auto
主要用于修饰自动类型的变量,局部变量就是自动类型。
如果没有赋初值,就是随机值。(因为在栈区)
eg:auto int a = 10;
//auto可以省略不写
(二)register
寄存器是硬件设备中的一小块空间,定义为rigister类型的变量可以使运算速度变快;但是其大小一般是4个字节,且个数有限,价格昂贵,所以尽量不要使用register。
由于register类型的变量是存储在寄存器上,因此无法取得它的地址。
(三)const
const修饰的变量是只读变量。不是常量。
1. const修饰局部变量和全局变量
const修饰的局部变量存储在内存中的栈区,可以通过指针修改(会报警告)
const修饰的全局变量存储在常量区的readonly区,不能通过指针修改
/***此处代码是为了理解***/
#include <stdio.h>const int number2 = 20;int main()
{const int number = 10;printf("number = %d",number);//可读number = 20; //对只读常量进行修改会报错//通过指针修改可以修改,但是会报警告int *p = &number;*p = 200;printf("number = %d\n",number);//const修饰的全局变量通过指针也不可修改int *p2 = &number2;*p2 = 200;
}
2. const修饰指针
const修饰的指针,const在谁前面谁就不能修改
/***此处代码是为了理解***/
#include <stdio.h>
int main()
{int number1 = 10;int number2 = 20;//*p1不能修改 p1可修改const int *p1 = &number1;*p1 = 200; //报错p = &number2; //可以执行//p2不能修改 *p2可以修改int * const p2 = &number1;*p2 = 200; //可执行p2 = &number2; //报错//*p3和p3都不能修改const int * const p3 = &number1;*p3 = 200; //报错p3 = &number2; //报错
}
(四)static
static 修饰的未初始化的变量在.bss段;
static 修饰的初始化的变量在.data段;
1. static修饰的局部变量
可以延长局部变量的生命周期,到程序结束的时候才会被释放。
作用域不会发生改变。
#include <stdio.h>void add1()
{static int num = 0;printf("num = %d\n",num++);
}
int main()
{for(int i=0;i<5;i++)add1();return 0;
}
输出结果:
2. static修饰的全局变量
static修饰的全局变量的生命周期是整个程序。
作用域:只能在本文件中使用。
3.static修饰函数
作用域:static修饰的函数只能在本文件中进行使用,不能跨文件使用。
(五)extern
外部声明,extern修饰的变量以及函数定义在其他文件中。
只能声明,不能定义。
(六)volatile
每次读值都要从内存中读取,不可以从cache中读取。
应用:
多线程操作时在全局变量前添加volatile
硬件操作时添加volatile
在中断处理函数中访问非自动类型的变量需要加volatile。(ARM接口技术)
三、结构体
结构体是一个构造类型,可以由不同类型的元素的成员组成。
结构体是一个类型,而非变量。
一般定义在全局,如果定义在函数中,只能在函数内部使用
(一)结构体类型定义
struct <结构体名称>
{<变量类型1> <变量名1>;<变量类型2> <变量名2>;...<变量类型n> <变量名n>;
}; //分号不能省略
eg: 定义一个结构体
#include <stdio.h>struct Student{char name[128];int age;float sore;
};
- 注:
-
- struct 是结构体的关键字,必须书写。
-
- 结构体名称可以省略,一般定义在结构体内部时使用这种方式,定义变量的方式略有不同。
-
- 结构体内部的成员是通过花括号来包括的
-
- 结构体类型的最后必须包括一个’;’
-
- 结构体内部的成员必须是确定大小的,所以结构体内部是不能写函数的。
-
- 结构体内部成员的数据类型可以相等,也可以不等
-
- 注意C语言中不能在定义结构体时在结构体内部进行赋值,即下面的定义是错误的
#include <stdio.h>
/***这种定义方法是错误的***/
struct Student{char name[128] = “lily”;int age = 10;float sore = 100;
};
(二)结构体变量的定义
结构体变量定义:
struct <结构体名称> 标识符;结构体指针变量:
struct <结构体名称> *标识符;
(三)结构体变量赋值
1. 定义结构体变量的同时进行赋值
struct Student s2 ={"xiao,18,99.9"};
//访问
printf("name:%s\n",s2.name);
2. 定义结构体类型的同时定义变量并进行赋值
struct Student{char name[128];int age;float sore;
}s1={"lily",17,99};
3. 在定义结构体变量时对指定成员进行赋值
struct Student{char name[128];int age;float sore;
}s1={.name="Lily"};
- 注:不能写成下面的形式
/***错误的写法***/
struct Student{char name[128];int age;float sore;
}s1={s1.name="Lily"};//这种是错误的写法
4. 在定义完结构体变量后,通过’.'进行赋值
struct Student{char name[128];int age;float sore;
};int main()
{struct Student s1;strcpy(s1.name,"Lily");s1.age = 18;s1.sore = 99;
}
(四)结构体成员访问
结构体变量:
通过 <结构体变量>.<成员>
来访问
结构体指针:
*p . <成员>
p -> <成员>
eg :使用指针访问结构体的值,实现两个虚数相加。
#include <stdio.h>struct vir
{int x;int y;
}s1={12,3},s2={65,32},s3;
//此时s1,s2,s3均为全局变量
//他们的成员也都是全局变量,存储在常量区的.bss段和.data段int main(int argc, const char *argv[])
{struct vir *p1 = &s1;struct vir *p2 = &s2;struct vir *p3 = &s3;p3->x=(p1->x)+(p2->x);p3->y=(p1->y)+(p2->y);printf("s1+s2=%d+%d*i\n",p3->x,p3->y);p3->x=(p1->x)-(p2->x);p3->y=(p1->y)-(p2->y);printf("s1-s2=%d+%d*i\n",p3->x,p3->y); return 0;
}
(五)结构体内部指针的使用
#include <stdio.h>
#include <stdlib.h>
struct Place
{int *arr;int size;int capacity;
};
int main()
{struct Place t;t.arr=(int *)malloc(4*50);//申请50个int型数据的空间大小t.size = 0;//相当于下标t.capacity = 50;//可以容纳的数据的个数
}
(六)结构体指针传参
eg:在堆区申请一段地址连续的空间
create函数,申请一块空间
write函数,向申请的空间内写值
#include <stdio.h>
#include <stdlib.h>//定义结构体类型
typedef struct Place{int* arr;int size;int capacity;
}Place_t;//创建空间
int create(Place_t *s,int size)
{if(!p){printf("struct is empty!\n");return -1;}s->arr = (int *)malloc(4*size);if(!(s->arr)){printf("create fail!\n");return -1;}s->size=0;s->capacity=size;printf("create %d please success!\n",size);return 0;
}
//向空间中写值
int write(Place_t *s,int num)
{if(!p){printf("struct is empty!\n");return -1;}if((s->size)<=(s->capacity)){ *((s->arr)+(s->size)) = num;(s->size)++;}else{ printf("capacity is full!\n");return -1; } return 0;
}int main(int argc, const char *argv[])
{Place_t a;int size;int num;printf("请输入需要多少空间:");scanf("%d",&size); create(&a,size);for(int i=0;i<size;i++){ printf("please input %d number:",i);scanf("%d",&num);if(write(&a,num)){printf("write fail!\n");}}for(int i=0;i<size;i++){printf("%d\n",*(a.arr+i));}//释放内存free(a.arr);a.arr=NULL;return 0;
}