C语言学习(九)多文件编程 存储类型 结构体

目录

  • 一、多文件编程
      • (一)不写头文件的方方式进行多文件编程
    • (二)通过头文件方式进行多文件编程
      • (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;
};
  • 注:
    1. struct 是结构体的关键字,必须书写。
    1. 结构体名称可以省略,一般定义在结构体内部时使用这种方式,定义变量的方式略有不同。
    1. 结构体内部的成员是通过花括号来包括的
    1. 结构体类型的最后必须包括一个’;’
    1. 结构体内部的成员必须是确定大小的,所以结构体内部是不能写函数的。
    1. 结构体内部成员的数据类型可以相等,也可以不等
    1. 注意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;
}  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/10917.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HC-06 蓝牙串口从机 AT 命令详解

HC-06 蓝牙串口从机 AT 命令详解 要使用 AT 命令&#xff0c;首先要知道 HC-06 的波特率&#xff0c;然后要进入 AT 命令模式。 使用串口一定要知道三要素&#xff0c;一是波特率&#xff0c;二是串口号&#xff0c;三是数据格式, HC-06只支持一种数据格式: 数据位8 位&#…

HTTP 连接详解

概述 世界上几乎所有的 HTTP 通信都是由 TCP/IP 承载的&#xff0c;客户端可以打开一条TCP/IP连接&#xff0c;连接到任何地方的服务器。一旦连接建立&#xff0c;客户端和服务器之间交换的报文就永远不会丢失、受损或失序 TCP&#xff08;Transmission Control Protocol&…

97. 交错字符串-----回溯、动态规划

题目链接 97. 交错字符串 - 力扣&#xff08;LeetCode&#xff09; 解答 递归回溯 题目所述为两个字符串交替组成第三个字符串&#xff0c;之前好像做过相似的题目&#xff0c;直接联想到可以考虑使用递归回溯的做法&#xff0c;让字符串s1和字符串s2分别作为起始字符串&…

Mybatis-Plus大批量插入数据到MySQL

MyBatis-Plus的saveBatch方法 GetMapping("/save1") public void save1() {// 数据准备List<MallOrder> orderList getMallOrderList();// mybatis-pluslong start System.currentTimeMillis();mallOrderService.saveBatch(orderList);System.out.println(&…

计算机服务器中了360后缀勒索病毒怎么解密,360后缀勒索病毒恢复

计算机网络技术的不断发展与应用&#xff0c;为企业的生产运营提供了极大便利&#xff0c;大大提高了企业的办公效率&#xff0c;为企业的生产运营注入了新的动力&#xff0c;但网络是一把双刃剑&#xff0c;在为企业提供便利的同时&#xff0c;也为企业的数据安全带来严重威胁…

google test 使用指南

目录 测试项目 calculator.h calculator.cpp test01.cpp 创建新项目 选择Google Test 选择要测试的项目 pch.cpp 加入依赖 设为启动项目 ​编辑 运行 ​编辑 关键点 测试项目 calculator.h #ifndef __CALCULATOR_H__ #define __CALCULATOR_H__#include <i…

Linux操作系统中管理磁盘的另外一种操作方式。即LVM——逻辑卷管理操作

在Linux操作系统中管理磁盘的一种方法名称——LVM&#xff0c;这种管理磁盘的优势。 1.使用LVM去管理磁盘可以在不影响原来数据的前提下去扩容磁盘空间或者是缩减磁盘空间。 在LVM中除了上层逻辑券可以扩容&#xff0c;下层的券组也可以扩容。 2.使用LVM管理的磁盘支持快照功…

MySQL中的子查询

子查询,在一个查询语句中又出现了查询语句 子查询可以出现在from和where后面 from 表子查询(结果一般为多行多列)把查询结果继续当一张表对待 where 标量子查询(结果集只有一行一列)查询身高最高的学生,查询到一个最高身高 列子查询(结果集只有一行多列) 对上表进行如下操作 …

韩顺平0基础学Java——第10天

p202-233 类与对象&#xff08;第七章&#xff09; 成员方法 person类中的speak方法&#xff1a; 1.public表示方法是公开的 2.void表示方法没有返回值 3.speak&#xff08;&#xff09;中&#xff0c;speak表示方法名&#xff0c;括号是形参列表。 4.大括号为方法体&am…

WPF之多种视图切换

1&#xff0c;View切换&#xff0c;效果呈现 视图1 视图2 视图3 2&#xff0c;在Xaml中添加Listview控件&#xff0c;Combobox控件。 <Grid ><Grid.RowDefinitions><RowDefinition Height"143*"/><RowDefinition Height"30"/>&l…

Leetcode经典题目之用队列实现栈

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、题目展示2、题目分析3、完整代码演示4、结语 1、题目展示 前面我们了解过如何实现队列…

第五百回 Get路由管理

文章目录 1. 概念介绍2. 使用方法2.1 普通路由2.2 命名路由 3. 示例代码4. 内容总结 我们在上一章回中介绍了"使用get显示Dialog"相关的内容&#xff0c;本章回中将介绍使用get进行路由管理.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

掌握MySQL常用的命令

前言 MySQL是一个流行的开源关系型数据库管理系统&#xff0c;广泛应用于各种应用场景。熟练掌握MySQL的常用命令&#xff0c;对于数据库管理员和开发人员来说至关重要。本文将介绍MySQL数据库的一些基础术语、SQL语言分类&#xff0c;以及DDL、DML、DQL和DCL等操作&#xff0…

C++类与对象的一些练习

1.设计一个名为Rectangle的矩形类&#xff0c;其属性为矩形的长和宽&#xff0c;能计算和输出矩形的周长和面积。 class Rectangle { public:Rectangle(int c0,int k0):m_c(c),m_k(k){}int length()//周长{return 2 * (m_c m_k);}int area()//面积{return m_c * m_k;} privat…

如何优雅简单地写 Controller 层代码?

本篇就来介绍一下&#xff0c;如何写好一个 controller &#xff0c;让你的接口变的更加优雅&#xff01; 一个完整的后端请求由 4 部分组成&#xff1a; 接口地址&#xff08;也就是 URL 地址&#xff09; 请求方式&#xff08;一般就是 get、set&#xff0c;当然还有 put、…

算法-排序详解

目录 前言 比较排序 选择排序 插入排序 冒泡排序 归并排序 快速排序 非比较类排序 计数排序 桶排序 基数排序 排序的稳定性 排序算法的题目 前言 计算机的工作之一就是对数据的处理&#xff0c;处理数据有一个常见的操作就是对数据排序&#xff0c;比如新闻系统总…

Linux——进程间通信

目录 一、进程通信的初步认识 1.1 进程间通信目的 1.2 进程间通信的种类 管道&#xff08;Pipes&#xff09; System V IPC POSIX IPC 三、管道 3.1 知识铺垫 3.2 匿名管道 3.2.1 基本概念 3.2.2 测试用例&#xff1a; 3.3 管道的行为 3.4 命名管道 3.4.1 基本概念…

Django Admin后台管理:高效开发与实践

title: Django Admin后台管理&#xff1a;高效开发与实践 date: 2024/5/8 14:24:15 updated: 2024/5/8 14:24:15 categories: 后端开发 tags: DjangoAdmin模型管理用户认证数据优化自定义扩展实战案例性能安全 第1章&#xff1a;Django Admin基础 1.1 Django Admin简介 Dj…

手撕C语言题典——反转链表

目录 前言 一.思路 1&#xff09;创建新链表 2&#xff09;创建三个指针 二.代码实现 搭配食用更佳哦~~ 数据结构之单单单——链表-CSDN博客 数据结构之单链表的基本操作-CSDN博客 前面学了单链表的相关知识&#xff0c;我们来尝试做一下关于顺序表的经典算法题~ 前言 反转…

Github 2024-05-12 php开源项目日报 Top10

根据Github Trendings的统计,今日(2024-05-12统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目10Filament: 加速Laravel开发的完美起点 创建周期:1410 天开发语言:PHP协议类型:MIT LicenseStar数量:12228 个Fork数量:1990 次关…