目录
- 一、多文件编程
- (一)不写头文件的方方式进行多文件编程
- (二)通过头文件方式进行多文件编程
- (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;
}