C-关键字(下)

文章目录

      • 循环控制
        • switch-case-break-default
        • do-while-for
          • getchar()
        • break-continue
        • goto
        • void
          • void*
      • return
      • const
          • const修饰变量
          • const修饰数组
          • const修饰指针
            • 指针补充
          • const 修饰返回值
      • volatile
      • struct
        • 柔型数组
      • union联合体
        • 联合体空间开辟问题
        • 利用联合体的性质,判断机器是大端还是小端
      • enum枚举
      • typedef
          • typedef vs #define
          • `typedef static int int32_t` 行不行

循环控制

switch-case-break-default

image-20230406140805011

int main()
{
	int day = 0;
	scanf("%d",&day);
	switch (day)//整形(int char short)||整形表达式
	{
	case 1:		//case是用来进行判定的
		printf("星期一\n");
		break;	//充当分支的作用,否则会将后面的都打印
	default:
		printf("不是星期一\n");
		break;
	}
	return 0;
}
  • 当一个case分支时要执行多条语句或者定义变量时最好加上代码块{}或者将众多代码封装为一个函数就行.
  • 当多条分支执行一条语句时,将break删除组合落为一个就行.
int main()
{
	int day = 0;
	scanf("%d",&day);
	switch (day)//整形(int char short)||整形表达式
	{
	case 1:	
	case 2:
	case 3:
		//case是用来进行判定的
		printf("要上课\n");
		break;	//充当分支的作用,否则会将后面的都打印
	default:
		printf("输入内容有误\n");
		break;
	}
	return 0;
}
  • default分支可以放在任何位置,只是为了好看并且符合语义放在最后.

  • break不要写成return,可以写但是不方便别人维护的时候好看,可以在循环的时候设置一个bool类型的标记位.

  • switch-case中绝对不能用const修饰组成的只读常量,必须是真正的常量.

int main()
{
	const int day = 0;
	scanf("%d",&day);
	switch (day)//整形(int char short)||整形表达式
	{
	case day:
		break;//编译报错
	case 1:	
	case 2:
	case 3:
		//case是用来进行判定的
		printf("要上课\n");
		break;	//充当分支的作用,否则会将后面的都打印
	default:
		printf("输入内容有误\n");
		break;
	}
	return 0;
}

do-while-for

循环条件初始化,循环判定,循环条件更新.

任何C程序,在默认编译好之后,运行时都会默认打开三个输入输出流.

image-20230406142354177

perror("hello world\n");

getchar()
  • 键盘中输入时,多读了一个\n

image-20230406143137250

  • 为什么返回值是int类型,不是char类型

字符char类型是8字节,[0,255],ASCII码表中都是合理的值,如果也设置是返回值是char.返回成功时是一个有效字符,如果获取失败,8个bit位只能表示所有的合法字符,但是无法表示返回失败的概念.说白了,char类型的返回值无法表示失败,太小了.

  • 键盘中输入的所有的内容或者输出的字符,或者往显示器中打印的,都是字符!

image-20230406143818789

printf的返回值就是表示一共打印了多少个字符.

int a=0; scanf("%d",&a);说白了就是将键盘中的字符按照类型格式化输入到变量a中.所以会将键盘显示器啥的都叫字符设备.

break-continue

  • break对比continue

image-20230407095415434

  • continue:在while()和do while()都是跳转到条件判断处,for()循环是跳转到条件更新处.

image-20230407095630498

goto

直接跳转到标签指定处,可以向上或者向下跳转.

  • goto 语句实现循环
int main()
{
	int i = 0;
start:
	printf("[%d] goto running ...\n", i);
	i++;
	if (i < 10)
	{
		goto start;
	}
	printf("goto end...\n");
	return 0;
}
  • goto语句只能在本函数块中使用,不能跨函数或者跨文件使用.

void

  • void不能定义变量.

    • void本身就被编译器定义为空类型,强制的不允许定义变量.

    • void大小是0不能开辟空间导致的,本身是空类型,理论上是不应该开空间的.即使开空间也仅仅是一个占位符.

    • 注意:不同的编译器对于void大小的规定也是不一样的.

image-20230407101805191

  • C语言函数可以不带返回值.默认的返回值就是int.避免别人误解,所以使用void告诉别人,我不想返回.只是起到一个占位符的作用,这个返回值无法接收.

image-20230407102602407

  • 告知编译器,这个函数不需要传参.

image-20230407103152292

void*
  • void* 可以定义变量只要是指针大小类型就是确定的.

  • void*可以被任何类型的指针接收.void*可以接收任意指针类型.

    • 库,系统接口的设计上,尽量设计为通用接口.例子中,既可以是int类型也可以是double类型.
    • image-20230407103612208
  • vs中void* 指针变量不能+±-,无法确定向前移动几个字节.而在Linux中是可以编译通过的,因为Linux中有确定的sizof(void)1字节大小.因为不同的平台看待void空间大小是不确定的.

  • 不能对void* 类型指针进行解引用.

return

  • 字符串类型 vs 字符串

C语言没有字符串类型,存在字符串,以\0结尾,不是数据长度,但是占据一字节的容量大小,字符串本身是没有名字的.使用字符数组访问.

  • 计算机中删除数据释放空间是否是将数据全部清空?

    计算机中删除数据本质只需要设置该数据无效即可(文件系统部分理解).所以下载数据很慢但是删除很快.

image-20230407140527770

调用函数,形成栈帧,函数返回,栈帧空间释放.函数栈帧中的数据并不会被释放,仅仅代表这个空间是可以被覆盖的.printf()也是函数,所以使用printf的时候会形成新的函数栈帧,覆盖之前show()函数栈帧的部分.

  • 开辟栈帧时,如何确定开辟多大的空间呢?

在调用函数之前,编译器可以通过定义变量的数量和类型,是可以预估这个函数应该是多少的空间的.不同的编译器预估的方式也是不同的.

  • 递归的情况会不断创建栈帧空间,会存在栈溢出的情况.

  • 为什么临时变量具有临时性?

    函数中的变量基本都是临时变量在一个函数栈帧中,函数返回栈帧空间被释放.所有的临时变量都是依托于函数栈帧开辟空间的.

int GetData()
{
	int x = 0x11223344;
	printf("get data success!\n");
	return x;
}
int main()
{
	int ret = GetData();
	printf("ret: %x\n",ret);
	return 0;
}
  • GetData()函数中的变量x在函数返回时已经被销毁,是如何交给ret的呢?

函数的返回值,通过寄存器eax的方式返回给函数调用方.

  • 有ret进行接收,就将eax中内容交给ret

image-20230407141527055

  • 没有ret接收,仍然放到eax中,但是函数并不会做任何处理.
  • main函数的返回值是给谁的呢?为什么经常是0?(进程部分讲解)

const

const修饰变量

为变量添加只读属性,const修饰的变量是不可直接被修改(二次赋值).通过指针就可以间接修改.

  • const修饰变量的意义?是在编译期间的处理

让编译器进行直接修改式检查.告诉其他人不可修改.(是一种软性要求,不是强制性约束)

  • 真正意义上的不可被修改,操作系统层面的处理.

image-20230407143043115

  • 数组开辟的空间大小必须是真常量.const修饰的变量vs中是编不过的.在Linux中是可以编过的,不同的平台支持的c的版本是不同的.
  • const只能在初始化的时候赋值,二次赋值时不允许的.
const修饰数组

数组中的元素都是不可被修改的.const int arr[] = {1,2,3,4,5};

const修饰指针

地址就是指针,提高CPU内存寻址的效率.

  • 地址是数据吗?是

  • 数据可以被保存吗?4字节空间存储,这个内存空间就叫做指针变量.

  • 任何一个变量名在不同的应用场景中代表不同的含义.

    int a=10;
    int* p=&a;
    p=&b;//p的空间,变量的属性,左值
    q=p; //p中的内容,数据的属性,右值
    
指针补充
  • &

整形变量为例,对应他的指针变量中存储的是变量4字节中的最低的那个地址空间.

  • *解引用

类型相同的时候,对指针解引用,指针所指向的目标.

int main()
{
	int  a = 10;
	const int *p1 = &a;//p指向的变量不可以直接修改
	p1 = 200;
	*p1 = 100;//error

	int const *p2 = &a;//p指向的变量不可以直接修改

	//const修饰的是指针变量p中地址内容不可直接被改变
	int* const p3 = &a;
	*p3 = 1200;
	int b = 20;
	p3 = &b;//error

	//const修饰的是指针变量p中地址内容不可直接被改变
	const int* const p4 = &a;
	*p4 = 200;//error
	p4 = &b;//error
	return 0;
}
  • 函数传参需要产生临时变量吗?

C中,任何函数参数都一定要产生临时变量,包括指针变量.

image-20230410111439339

const 修饰返回值

如果不想用函数返回值修改函数中变量的值时,可以选择使用const修饰返回值.

const int* GetVal()
{
	static int a = 10;
	return &a;
}
int main()
{
	const int* p = GetVal();//外部接收使用const修饰
	*p = 100;//error
}

volatile

  • 内存被覆盖的情况

不让CPU进行优化,每次都去访问内存,而不是优化被放进寄存器中数据的值,一直访问寄存器中的数据.

#include <stdio.h>
int pass = 1;
//volatile int pass = 1;
int main()
{
	while(pass)
    {}
    return 0;
}
  • 不加volatile

image-20230410113350227

  • 加上volatile

image-20230410113511509

const volatile int a = 10;
在vs2013和gcc 4.8中都能编译通过
const是在编译期间起效果
volatile在编译期间主要影响编译器,形成不优化的代码,进而影响运行,故:编译和运行都起效果。
const要求你不要进行写入就可以。volatile意思是你读取的时候,每次都要从内存读。
两者并不冲突。
虽然volatile就叫做易变关键字,但这里仅仅是描述它修饰的变量可能会变化,要编译器注意,并不是它要求对应变量必须变化!这点要特别注意

struct

#define NUM 64
struct stu
{
	char name[NUM / 2];
	int age;
	char sex;
	char addr[NUM];
}a,c,b;//struct类型就是类型,和int啥的定义变量是相同的
int main()
{
	struct stu x;
	strcpy(x.name,"张三");
	//x.name = "张三";//error 支持整体初始化,不支持整体赋值
	x.age = 18;
	
	struct stu* p = &x;
	printf("sut.name:%s\n",p->name);
	printf("sut.name:%s\n",(*p).name);
	//为什么结构体访问会存在两种形式?
	//结构体可能贯穿多个函数,这时候传指针就很节省空间并且效率高
	//在日常访问的时候使用.更方便
}
  • vs中结构体必须有一个成员,不支持空结构体.Linux中gcc可以定义,大小是0

柔型数组

  • 必须放在结构体内.

  • 首元素最好不是柔性数组,建议使用时前面最好还有一个有效的成员.

  • 柔性数组是不占用结构体空间的.所以想要动态开辟结构体大小的空间时,需要根据设定大小和类型自定义开辟.

struct data
{ 
	int num;
	int arr[];
};
int main()
{
	struct data d;
	struct data* p = malloc(sizeof(struct data)+sizeof(int)*10);
	p->num = 10;
	for (int i = 0; i < p->num; i++)
	{
		p->arr[i] = i;
	}
	free(p);
}

union联合体

union un
{
	int a;
	char b;
};
int main()
{
	union un u;
	u.a = 10;
	union un* p_un = &u;
	p_un->a = 20;

	printf("%d\n",sizeof(union un));//4

	return 0;
}

联合体空间开辟问题

  • 联合体的地址和联合体中最大元素的地址是相同的

image-20230410125434021

  • 联合体中最小元素b的地址也是联合体起始地址,也就是最低地址.

image-20230410125657111

所以,联合体中的所有变量的起始地址在数字上都是相同的,取最大变量的大小开辟空间,所有变量以放射状的方式从低地址向高地址开辟空间.

image-20230410125918607

  • 开辟的空间是属于大家的,每个变量都认为自己独占所有空间,每一个元素都是第一个元素.

利用联合体的性质,判断机器是大端还是小端

image-20230410130413225

int main()
{
	union un u;
	u.a = 1;
	if (u.b == 1)
	{
		printf("小端机器");
	}
	else
	{
		printf("大端机器");
	}
}

image-20230410135756520

enum枚举

存储常量.制作整合一些具有强相关性的常量.使用英文单词相对于数字,具有自描述性.

enum en
{
	RED,
	BLACK,
	BLUE,
	GREEN
};
int main()
{
	int a = BLUE;//如果直接用数字初始化a,需要添加注释别人才能看懂
	printf("%d\n",a);//2

	enum en c = BLUE;
	printf("%d\n",RED);//0
	printf("%d\n",BLACK);//1
}

typedef

类型重命名

typedef unsigned int u_int;
struct data
{ 
	int num;
	int arr[];
} a;//a 叫全局定义的一个变量
typedef struct Student
{
	int num;
	char name[10];
	char sex;
}Stu;//Stu 就是结构体类型

typedef int a[10];//a是一个数组类型
int main()
{
	u_int t = -10;
	Stu s;
	a b;
	return 0;
}
typedef vs #define
  • 类型重命名并不是简单的某种类型替换,应该理解为一个全新的类型,而不是替换之后*先和那个变量结合.

image-20230410144258209

image-20230410144511453

  • typedef 之后不能再引入其他关键字来修饰类型

image-20230410144712343

typedef static int int32_t 行不行
  • 存储类型关键字(5个)

auto :声明自动变量,一般不使用
extern :声明变量是在其他文件中声明
register :声明寄存器变量
static :声明静态变量
typedef :用以给数据类型取别名(但是该关键字被分到存储关键字分类中,虽然看起来没什么相关性)

存储类型关键字不可以同时出现,在一个变量定义的时候只能有一个.报错:指定一个以上的存储类

  • 其他关键字(3个)

    const :声明只读变量
    sizeof :计算数据类型长度
    volatile :说明变量在程序执行中可被隐含地改变

  • 控制语句关键字(12个)

1. 循环控制(5个)
for :一种循环语句
do :循环语句的循环体
while :循环语句的循环条件
break :跳出当前循环
continue :结束当前循环,开始下一轮循环
2. 条件语句(3个)
if : 条件语句
else :条件语句否定分支
goto :无条件跳转语句
3. 开关语句 (3个)
switch :用于开关语句
case :开关语句分支
default :开关语句中的“其他”分支
4. 返回语句(1个)
return :函数返回语句(可以带参数,也看不带参数)
  • 数据类型关键字(12个)

    char :声明字符型变量或函数
    short :声明短整型变量或函数
    int : 声明整型变量或函数
    long :声明长整型变量或函数
    signed :声明有符号类型变量或函数
    unsigned :声明无符号类型变量或函数
    float :声明浮点型变量或函数
    double :声明双精度变量或函数
    struct :声明结构体变量或函数
    union :声明共用体(联合)数据类型
    enum :声明枚举类型
    void :声明函数无返回值或无参数,声明无类型指针  
    

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

运行时内存数据区之虚拟机栈——动态链接、方法返回地址与一些附加信息

动态链接&#xff08;Dynamic Linking&#xff09;——指向运行时常量池的方法引用 每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用。包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。比如&#xff1a;invokedynamic指令。…

( “树” 之 DFS) 101. 对称二叉树 ——【Leetcode每日一题】

101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示&#xff1a…

聚焦元宇宙赋能产业,打造数字世界,“OFweek2023广州元宇宙产业发展高峰论坛”圆满落幕!

2023年4月12日下午&#xff0c;由广东潮域科技有限公司、OFweek维科网共同主办&#xff0c;OFweek人工智能网承办的“OFweek 2023 广州元宇宙产业发展高峰论坛”在广州保利世贸博览馆1号馆盛大举办。 元宇宙产业相关技术及设备&#xff0c;包括VR&#xff0f;AR、虚拟现实、物联…

springboot配置跨域问题

近期自己搭建项目时&#xff0c;遇到一个跨域问题。我们以前项目解决跨域是在controller上加一个跨域注解CrossOrigin(allowCredentials "true")&#xff0c;很方便。但是在我自己搭建的项目中&#xff0c;启动时竟然报错了&#xff0c;错误如下&#xff1a; When …

不会写代码也能做自动化?推荐一款自动化测试神器

在软件测试这条道路上&#xff0c;大部分的职业技能发展道路都会是纯业务手工测试→自动化测试→性能测试→安全测试/测试开发。 但是却有着一部分人起初进入软件测试这一行看重的就是软件测试属于IT行业&#xff0c;门槛比较低&#xff0c;不需要代码基础。 这就导致了这一部…

第07章_面向对象编程(进阶)

第07章_面向对象编程(进阶) 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 关键字&#xff1a;this 1.1 this是什么&#xff1f; 在Java中&#xff0c;this关键字不算难理解…

<数据结构> 链表 - 单链表(c语言实现)

B.最简单结构的链表——不带哨兵位单链表的实现&#xff08;关于哨兵位结点&#xff09; 一、不带哨兵位单链表结点的创建1.1 typedef 链表的数据类型 1.2 结点的结构体创建 二、单链表要实现的功能 三、需要包含的头文件四、函数接口一览为什么有些函数参数传递的是二级指针&a…

【大数据之Hadoop】十一、MapReduce之Shuffle、MapTask、ReduceTask工作机制

1 Shuffle机制 对于排序而言分为两个阶段&#xff0c;MapTask后和ReduceTask前。 2 MapTask工作机制 MapTask并行度由切片个数决定&#xff1b;切片个数由切片大小&#xff08;切片大小取决于块大小、maxsize&#xff08;Long的最大值&#xff09;和minsize&#xff08;默认为…

设计模式之模板模式(C++)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 一、模板模式是什么&#xff1f; 模板模式是一种行为型的软件设计模式&#xff0c;在父类中定义了一个模板算法&#xff0c;只实现…

Android---MVC/MVP/MVVM的演进

目录 一个文件打天下 一个文件--->MVC MVC--->MVP MVP--->MVVM 6大设计原则 完整demo 我们通过"#字棋"游戏来展现MVC-->MVP-->MVVM 之间的演进 一个文件打天下 数据、视图以及逻辑都放在一个 class 里面。而一个 class 里最多 500 行代码&…

GPT-4 和ChatGPT API的定价分析

OpenAI发布了他们的ChatGPT新机器学习模型GPT-4。GPT-4是GPT-3的一大进步&#xff0c;GPT-3是当前ChatGPT免费版本(GPT 3.5 Turbo)所运行的模型的基础&#xff0c;今天我们也来凑个热点&#xff0c;研究一下它们的定价 GPT-4新的功能 GPT-4可以在对话中使用图像&#xff0c;并…

Mybatis(七)Mybatis的日志体系

在介绍Mybatis日志实现前&#xff0c;我们先了解下java的日志体系以及日志框架的发展&#xff0c;目前比较常用的日志框架有下面几个&#xff1a; 而JCL和SLF4J属于日志接口&#xff08;没有日志具体实现&#xff09;&#xff0c;提供统一的日志操作规范&#xff0c;而日志的实…

NumPy 秘籍中文第二版:四、将 NumPy 与世界的其他地方连接

原文&#xff1a;NumPy Cookbook - Second Edition 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 在本章中&#xff0c;我们将介绍以下秘籍&#xff1a; 使用缓冲区协议使用数组接口与 MATLAB 和 Octave 交换数据安装 RPy2与 R 交互安装 JPype将 NumPy 数组发送到 J…

什么是Lambda表达式?

什么是Lambda表达式 可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式&#xff1a;它没有名称&#xff0c;但它有参数列表、函数主体、返回类型&#xff0c;可能还有一个可以抛出的异常列表。 匿名&#xff1a;它不像普通的方法那样有一个明确的名称&#xff1…

GPT 任务指令 = 定义角色 + 背景信息 + 任务目标 + 输出要求

GPT 任务指令 定义角色 背景信息 任务目标 输出要求 环境 GPT-4 0. 你是一名专业的导游&#xff0c;负责为我生成旅游计划&#xff0c;现在我来北京旅游&#xff0c;需要你为我生成一份 3天2晚的北京旅游规划。我的要求是&#xff1a;1.地点包括故宫、军播和环球影城。 2…

pytorch搭建ResNet50实现鸟类识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f366; 参考文章地址&#xff1a; 365天深度学习训练营-第J1周&#xff1a;ResNet-50算法实战与解析 &#x1f356; 作者&#xff1a;K同学啊 理论知识储备 深度残差网络ResNet&#xff08;dee…

OceanBase 4.1 发版 | 一个面向开发者的里程碑版本

欢迎访问 OceanBase 官网获取更多信息&#xff1a;https://www.oceanbase.com/ 2022 年 8 月&#xff0c;OceanBase发布了 4.0 版本&#xff08;小鱼&#xff09;&#xff0c;作为业内首个单机分布式一体化架构&#xff0c;兼顾了分布式架构的扩展性和集中式架构的性能优势&…

优思学院|职场达人有什么晋升秘诀?

作为职场人士&#xff0c;升职晋升是我们一直追求的目标。然而&#xff0c;在职场中&#xff0c;竞争是激烈的&#xff0c;只有那些真正做到了突出表现和积极进取的人才能获得晋升机会。这里将分享七个职场达人的晋升秘诀&#xff0c;希望对那些正在寻找升职机会的人有所帮助。…

Linux Shell 实现一键部署Nginx

nginx前言 nginx [engine x] 是 HTTP 和反向代理服务器、邮件代理服务器和通用 TCP/UDP 代理服务器&#xff0c;最初由Igor Sysoev编写。很长一段时间以来&#xff0c;它一直在许多负载重的俄罗斯网站上运行&#xff0c;包括 Yandex、 Mail.Ru、 VK和 Rambler。根据 Netcraft …

Spring的创建与Bean对象的存取

文章目录&#xff1a;一.Spring项目的创建1.先创建maven项目 2.添加国内源 3.添加spring依赖 4.创建spring配置文件 5.创建启动类 二.Bean对象的创建和读取1.Bean对象的创建与存储方式&#xff08;1&#xff09;类注解 &#xff08;2&#xff09;方法注解 &#xff08;3&#x…
最新文章