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

news2024/10/6 22:28:40

目录

  • 一、多文件编程
      • (一)不写头文件的方方式进行多文件编程
    • (二)通过头文件方式进行多文件编程
      • (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.coloradmin.cn/o/1665593.html

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

相关文章

Rust学习笔记(上)

前言 笔记的内容主要参考与《Rust 程序设计语言》&#xff0c;一些也参考了《通过例子学 Rust》和《Rust语言圣经》。 Rust学习笔记分为上中下&#xff0c;其它两个地址在Rust学习笔记&#xff08;中&#xff09;和Rust学习笔记&#xff08;下&#xff09;。 编译与运行 Ru…

LeetCode - 0088 合并两个有序数组

题目地址&#xff1a;https://leetcode.cn/problems/merge-sorted-array/description/ 引言&#xff1a;话接上回&#xff0c;由于上次面试官着急下班&#xff0c;面试不得不提前终止&#xff0c;这不&#xff0c;他又找我去面试了 面试官&#xff1a;你好&#xff0c;小伙子&a…

(二刷)代码随想录第4天|24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点

24. 两两交换链表中的节点 24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 帮你把链表细节学清楚&#xff01; | LeetCode&#xff1a;24. 两两交换链表中的节点_哔哩哔哩_bilibili 给你一个链表&#xff0c;两两交换其…

电影网站|基于SSM+vue的电影网站系统(源码+数据库+文档)

电影网站 目录 基于SSMvue的电影网站系统 一、前言 二、系统设计 三、系统功能设计 1 系统功能模块 2 管理员功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道…

C语言 | Leetcode C语言题解之第83题删除排序链表中的重复元素

题目&#xff1a; 题解&#xff1a; struct ListNode* deleteDuplicates(struct ListNode* head) {if (!head) {return head;}struct ListNode* cur head;while (cur->next) {if (cur->val cur->next->val) {cur->next cur->next->next;} else {cur …

Rancher-Kubewarden-保姆级教学-含Demo测试

一、什么是Kubewarden&#xff1f; What is Kubewarden? | Kubewarden 1、就是容器集群的准入策略引擎。 1、使用的策略其实就是k8s原生的security context. 2、使用WebAssembly来编写策略。 1、WebAssembly&#xff0c;可以使用擅长的开发语言来编写策略。&#xff08;下面的…

撤销 git add 操作(忽略被追踪的文件)

文章目录 引言I git rm命令来取消暂存【推荐】II 撤销特定文件的暂存状态2.1 git rese2.2 git restoresee also引言 应用场景: 修改.gitignoregitignore只能忽略那些原来没有被追踪的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先…

Python 开发 框架安全:Django SQL注入漏洞测试.(CVE-2021-35042)

什么是 Django 框架 Django 是一个用 Python 编写的 Web 应用程序框架。它提供了许多工具和库&#xff0c;使得开发 Web 应用程序变得更加容易和高效。Django 遵循了“MTV”&#xff08;模型-模板-视图&#xff09;的设计模式&#xff0c;将应用程序的不同组件分离开来&#x…

【智能算法】鹭鹰优化算法(SBOA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;Y Fu受到自然界中鹭鹰生存行为启发&#xff0c;提出了鹭鹰优化算法&#xff08;Secretary Bird Optimization Algorithm, SBOA&#xff09;。 2.算法原理 2.1算法思想…

stl学习以及abc比赛例题

1.引例 一提到查找&#xff0c;我们一上来想的肯定是find()函数或者search()函数&#xff0c;但是这种查找的底层逻辑终究是用顺序查找的方式&#xff0c;运行的时间成本非常高昂&#xff0c;所以平时能不用就不用&#xff0c;比赛的时候用这种查找和自己while遍历&#xff0c…

哈希表(unordered_set、unordered_map)

文章目录 一、unordered_set、unordered_map的介绍二、哈希表的建立方法2.1闭散列2.2开散列&#xff08;哈希桶/拉链法&#xff09; 三、闭散列代码&#xff08;除留余数法&#xff09;四、开散列代码&#xff08;拉链法/哈希桶&#xff09; 一、unordered_set、unordered_map的…

SpringSecurity集成第三方登录

SpringSecurity 集成第三方登录 认证及自定义流程 首先我们提供一个实现了AbstractAuthenticationProcessingFilter抽象类的过滤器&#xff0c;用来代替UsernamePasswordAuthenticationFilter逻辑&#xff0c;然后提供一个AuthenticationProvider实现类代替AbstractUserDetail…

【数据结构】浅谈

✨✨✨专栏&#xff1a;数据结构 &#x1f9d1;‍&#x1f393;个人主页&#xff1a;SWsunlight 目录 一、概念&#xff1a; 二、物理结构&#xff1a; 1、顺序存储结构&#xff1a; 2、链式存储结构&#xff1a; 3、数据索引存储结构: 4、数据散列存储结构&#xf…

数学学习笔记1——二次函数中的数形结合

二次函数中的数形结合 一、解一元二次不等式 基本方法&#xff1a;配方。 x 2 − 4 x 3 < 0 → ( x − 2 ) 2 < 1 → ∣ x − 2 ∣ < 1 → 1 < x < 3 x^2-4x3<0\to(x-2)^2<1\to\lvert x-2\rvert<1\to1<x<3 x2−4x3<0→(x−2)2<1→∣x−…

璩静是为了薅百度羊毛

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 百度副总裁璩静离职了&#xff0c;网传她的年薪是1500万&#xff0c;而璩静在4月24日注册了一个文化传媒公司&#xff0c;大家都认为璩静是在为离职做准备。但松松我认为不是。 我认为&#xff1a;璩静成立新公司是…

【ORACLE战报】2024.4月最新OCP考试喜报.

课程介绍 DBA数据库管理必备认证&#xff1a;ORACLE OCP 19C 教材下载 ORACLE OCP 19C 官方电子教材 ORACLE OCP 12C官方电子教材 题库下载 ORACLE 19C题库 &#xff08;083384题、082362题&#xff09;-2024答案修正版.rar 所有的收获都是默默耕耘的成果 2024.4月【最新考试成…

苍穹外卖项目---------收获以及改进(9-12)

①Spring Task-------实现系统定时任务 概念&#xff1a; 应用场景&#xff1a; 使用步骤&#xff1a; 实现订单超时和前一天派送中的订单的自动任务处理&#xff1a; Component Slf4j public class Mytask {Autowiredprivate OrderServiceimpl orderServiceimpl;/*** 处理订…

parallels desktop19最新免费Mac电脑虚拟机软件

Parallels Desktop是一款运行在Mac电脑上的虚拟机软件&#xff0c;它允许用户在Mac系统上同时运行多个操作系统&#xff0c;比如Windows、Linux等。通过这款软件&#xff0c;Mac用户可以轻松地在同一台电脑上体验不同操作系统的功能和应用程序&#xff0c;而无需额外的硬件设备…

C++入门——命名空间、缺省参数、函数重载、引用、内敛函数、auto关键字

目录 前言 一、什么是C 1.1 C关键字(C98) 二、命名空间 2.1 命名空间定义 1.正常命名空间的定义 2.命名空间的定义可以嵌套 3.同名的命名空间会合并 2.2 命名空间的使用 三、C输入&输出 四、缺省参数 4.1 缺省参数概念 4.2 缺省参数分类 五、函数重载 5.1 …

N5183B是德科技n5183b信号源

181/2461/8938产品概述&#xff1a; 简  述&#xff1a; N5183B 频率范围&#xff1a;9 kHz 至 20 GHz&#xff0c;具有 AM、FM、相位调制功能。N5183B MXG X 系列微波模拟信号发生器拥有 9 kHz 至 40 GHz 的频率覆盖范围&#xff0c;以及接近 PSG 级别的相位噪声性能&…