C语言杂谈

在这里插入图片描述
努力扩大自己,以靠近,以触及自身以外的世界

文章目录

  • 什么是定义?什么是声明?什么是赋值?什么是初始化?
  • 什么是生命周期?什么是作用域?全局变量?局部变量?
  • sizeof是函数吗?关键字!!!
  • signed、unsigned 关键字
  • static关键字
  • abs函数和fabs函数
  • 空结构体占多大空间?
  • 柔性数组
  • union
  • enum
  • typedef
  • 取整和取模
  • 内存对齐——为什么需要内存对齐?
  • 宏定义#define
  • 指针和数组的关系?
  • 向特定地址中写入数据?
  • #和##
  • assert是宏而不是函数
  • malloc申请0字节空间
  • 函数参数的传递发生在函数调用之前
  • 可变参数列表

什么是定义?什么是声明?什么是赋值?什么是初始化?

定义:定义就是创建一个对象,为这个对象分配一块内存并给它取上一个名字,这个名字就是我们经常所说的变量名或对象名

声明:告知编译器这个变量名已经被占用,所有的变量声明时不能设置初始值,因为声明时并没有给出存储空间

赋值:给开辟好的空间赋上数据

初始化:一种特殊的赋值,在变量创建的阶段给上数据,初始化只能有一次

// 定义并初始化全局变量
int global = 10;// 函数声明
void myFunction();int main() 
{// 声明并初始化局部变量int local;local = 20;// 调用函数myFunction();// 打印全局变量和局部变量的值printf("Global: %d\n", global);printf("Local: %d\n", local);return 0;
}// 函数定义
void myFunction() 
{// 赋值操作global = 30;
}

什么是生命周期?什么是作用域?全局变量?局部变量?

生命周期:从开辟到释放所经历的这一时间段

作用域:变量的有效作用范围

全局变量:在整个程序的任何地方都是可用和可访问的

局部变量:只能在变量特定的作用域内起作用

// 全局变量,定义在函数外部,可以在整个程序中使用
int global = 10;// 函数定义
void myFunction() 
{// 局部变量,定义在函数内部,只能在函数内部使用int local = 20;// 访问全局变量和局部变量,并打印它们的值printf("Global: %d\n", global);printf("Local: %d\n", local);
}int main() 
{// 调用函数myFunction();// 尝试访问局部变量,会导致编译错误// printf("Local in main: %d\n", local);// 访问全局变量printf("Global in main: %d\n", global);return 0;
}

sizeof是函数吗?关键字!!!

说来惭愧,当听到问sizeof是函数吗?第一时间就想到它后面接的是(),理所当然的认为sizeof就是函数…

可是sizeof也可以不加()使用啊

int main()
{int val = 100;printf("sizeof() : %d\nsizeof : %d\n", sizeof(val), sizeof val);return 0;
}

在这里插入图片描述

但是!!!sizeof 在计算变量所占空间大小时,括号可以省略,而计算类型(模子)大小时不能省略。

在这里插入图片描述

signed、unsigned 关键字

直接上代码

int main()
{char a[1000];int i;for(i=0; i<1000; i++){a[i] = -1-i;}printf("%d",strlen(a));return 0;
}

乍一看,很简单,再一看,嘶~~~好像要思考一下,看到负数就想到负数在计算机中的存储形式,以补码的形式存储,最高位符号位为1。char类型占1字节即8比特位,所以是从-128~127一共256个数,但是strlen是以\0为结尾,所以一共255个数。

正数的原码反码补码都是一样,没什么好说,而负数的存储是以补码的形式存储,所以负数的存储首先就需要将源码转换为补码,然后在将其存入到内存中。注意!!!!就是这么一个过程,先转换,然后存入。所以我数据的存储是不关注你存放在哪里,存放好之后我能够读取出来就行,所以signed和unsigned两种类型的区别就是我是否关注符号位,然后进行不同的读取。

正数负数我该怎么存就怎么存,有无符号是你读取的方式,读出来多少是你的事

再来一段代码

int i = -20;
unsigned j = 10;

i+j 的值为多少?为什么?

此时的结果随着你读取的方式而变化,如果使用printf(“%d”, i + j)的话,结果为-10。当使用printf(“%u”, i + j)的话,结果为42亿多。

static关键字

static关键字在修饰变量时有两种情况:修饰全局变量,修饰局部变量

修饰全局变量:被修饰的全局变量也称静态全局变量,改变了该全局变量的作用域,使得该变量只在声明它的源文件中可见,而在其他源文件中是不可见的

修饰局部变量:生命周期扩展到整个程序的执行期间,但作用域仍限于声明它的函数内部,整个执行期间只初始化一次,且默认为0

修饰函数:函数的作用域限定在声明它的文件内部,使得该函数对于其他文件是不可见的

void function() 
{static int x; // 静态变量x++;printf("x: %d\n", x);
}

abs函数和fabs函数

abs用于整形的绝对值,fabs用于浮点型的绝对值

空结构体占多大空间?

struct empty
{};int main()
{empty emp;printf("empty struct size : %d\n", sizeof(emp));return 0;
}

一般而言空结构体的大小是给1字节,但是具体是多少还是依编译器。编译器认为任何一种数据类型都有其大小,用它来定义一个变量能够分配确定大小的空间。(vs中直接报错…)

柔性数组

在C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构中的柔性数组成员前面必须至少有一个其他成员,且一个结构体只能有一个柔性数组。

柔性数组在定义时动态开辟空间,不影响结构体的大小

struct array1
{int lenth;int arr[];
};struct array2
{int lenth;int *arr;
};int main()
{struct array1 a;struct array2 b;printf("size : %d\n", sizeof(a));printf("size : %d\n", sizeof(b));return 0;
}

在这里插入图片描述

union

union也称联合体或者共用体,顾名思义,就是联合体内所有数据共用一块内存,这块内存大小是成员类型最大的字节数。

可以用union来验证大小端

union U
{int a;char b;
};int main()
{union U u1;u1.a = 1;  //0x0001;if (u1.b == 1){printf("小端机\n");}else{printf("大端机\n");}return 0;
}

enum

enum枚举类型允许对一批整形变量进行命名,提高代码可读性

不需要实例化对象

enum Weekday {Monday = 1,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};

sizeof枚举类型的大小是多少?

enum类型的大小并不是固定的,enum类型的大小是由编译器来决定的,可能是4字节也可能是8字节,并且还与你给出的值有关

enum Week  //demo1
{day1 = 0x11223344,day2,day3
};
// sizeof(enum Week) = 4
enum Week  //demo2
{day1 = 0x1122334455,day2,day3
};
// sizeof(enum Week) = 8

typedef

给一个已经存在的数据类型(注意:是类型不是变量)取一个别名,而非定义一个新的数据类型

注意:typedef在给类型取别名时,完全继承了原始类型的属性,但是不能和其他类型修饰符进行组合使用来修改这些属性

typedef int int32;
int main()
{// unsigned int32 a = 0; // 错误int32 b = 1;
}    

在这里插入图片描述

取整和取模

整数除法中,C语言的行为规则是向零取整

当求模运算中至少一个操作数为负数时,C语言的求模运算结果的符号由被除数的符号决定。

内存对齐——为什么需要内存对齐?

简要的说,数据按照特定的规则放到对应的地址上就是内存对齐,内存对齐可以增强系统性能,因为对于没有对齐的数据,操作系统读取数据可能需要多次的内存访问,而内存对齐后数据就在对齐边界上,操作系统一次内存访问就可以读取数据,提高性能

在这里插入图片描述

宏定义#define

宏定义的常量或者宏函数都是在预处理阶段直接进行机械替换,因此使用宏函数可以免去函数调用的开销,提高性能。但是定义的这些都没有类型安全检查,并且存在优先级问题,需要谨慎使用

宏的作用域:宏的作用域是在其定义的地方向后

void func1()
{int num = M; //不替换
}
int main()
{#define M 10int num = M; //替换func1();func2();return 0;
}
void func2()
{int num = M; // 替换
}

指针和数组的关系?

指针和数组没有关系!!!指针的大小为4/8字节,数组的大小为(类型 * 数据)

指针存放地址,该地址是数据存放的地址。数组存放数据,只是数组名类似于指针,是数组中第一个元素的地址

指针是一个变量,可以指向任何数据类型,而数组是一个固定长度的数据集合

指针可以被重新赋值指向不同的内存地址,而数组名则不能被重新赋值

向特定地址中写入数据?

指针指向某个地址,如果权限允许,我们可以向该地址中写入数据。一般来说关注的都是数据而不是地址,当想向特定地址写入数据的话那该怎么做呢?

假设向0x12ff7c的地址中写入数据

int main()
{int *p = (int*)0x12ff7c;*p = 10;//又或者 *(int*)0x12ff7c = 10;return 0;
}

#和##

#号:在宏定义中,#号用于将参数转换为字符串字面值。这个过程称为字符串化。当#号放在宏参数前面时,它将该参数转换为一个以双引号包围的字符串字面值

#define STRINGIZE(x) #x
printf("%s\n", STRINGIZE(hello)); // 将输出 "hello"

##号:在宏定义中,##号用于连接两个标识符或符号

#define CONCAT(x, y) x##y
int ab = 10;
printf("%d\n", CONCAT(a, b)); // 将输出 10

##号只能用于连接标识符或符号,不能用于连接字符串或数字

assert是宏而不是函数

    _ACRTIMP void __cdecl _wassert(_In_z_ wchar_t const* _Message,_In_z_ wchar_t const* _File,_In_   unsigned       _Line);#define assert(expression) (void)(                                                       \(!!(expression)) ||                                                              \(_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \)

assert只存在于debug版本中,不存在release版本中,assert的作用是定位错误,而不是排除错误

malloc申请0字节空间

申请0字节函数返回的是正常地址,因为函数的返回值规定了返回NULL代表申请失败,而申请0字节是成功的,但是返回的地址是不可以使用的,强制使用会导致未定义行为

malloc除了给到你申请的空间外,还会额外给你更多的空间来存放元信息

函数参数的传递发生在函数调用之前

int addNum(int num1, int num2)
{return num1 + num2;
}int main()
{int ret = addNum(1, 2, 3, 4);printf("ret = %d\n", ret);return 0;
}

在这里插入图片描述

在C语言中,如果函数没有参数,那么对该函数进行传参也是可以,因为参数传递发生在函数调用之前

void Empty()
{}int main()
{Empty(1, 2, "123");return 0;
}

可变参数列表

使用C语言的可变参数列表需要包含<stdarg.h>这个头文件,里面包含有几个宏,例如va_start、va_arg、va_end和va_copy,大致的使用流程:

#include <stdio.h>
#include <stdarg.h>Myadd(int n, ...)
{va_list args; //1. 定义va_list类型变量va_start(args, n); //2. 初始化args变量int sum = 0;for (int i = 0; i < n; i++){sum += va_arg(args, int); //去除参数}va_end(args); //args置空return sum;
}int main()
{int ret1 = Myadd(4, 1, 2, 3, 4);int ret2 = Myadd(3, 2, 3, 4);printf("ret1=%d   ret2=%d\n", ret1, ret2);return 0;
}

其中va_list是typedef的,原型为char*

在这里插入图片描述

其他几个都是宏函数

在这里插入图片描述

    //这个宏通常用于确定参数在堆栈上的对齐方式。	#define _INTSIZEOF(n)          ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1)) #define _ADDRESSOF(v)           (&(v))#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))#define __crt_va_arg(ap, t)     (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))#define __crt_va_end(ap)        ((void)(ap = (va_list)0))

在这里插入图片描述

    //这个宏通常用于确定参数在堆栈上的对齐方式。	#define _INTSIZEOF(n)          ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1)) #define _ADDRESSOF(v)           (&(v))#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))#define __crt_va_arg(ap, t)     (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))#define __crt_va_end(ap)        ((void)(ap = (va_list)0))

在这里插入图片描述

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

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

相关文章

HCIA-RS基础-VLAN路由

目录 VLAN 路由1. 什么是 VLAN 路由2. VLAN 路由的原理及配置3. VLAN 的缺点和 VLAN Trunking4. 单臂路由配置 总结 VLAN 路由 1. 什么是 VLAN 路由 VLAN 路由是指在虚拟局域网&#xff08;VLAN&#xff09;之间进行路由转发的过程。传统的 VLAN 配置只能在同一个 VLAN 内进行…

LCD1602显示屏

LCD1602显示 概述 LCD1602&#xff08;Liquid Crystal Display&#xff09;是一种工业字符型液晶&#xff0c;能够同时显示 1602 即 32 字符(16列两行) 引脚说明 //电源 VSS -- GND VDD -- 5V //对比度 VO -- GND //控制线 RS -- P1.0 RW -- P1.1 E -- P1.4 //背光灯 A -- 5…

在ChatGPT中,能用DALL·E 3编辑图片啦!

4月3日&#xff0c;OpenAI开始向部分用户&#xff0c;提供在ChatGPT中的DALLE 3图片编辑功能。 DALLE 3是OpenAI在2023年9月20日发布的一款文生图模型&#xff0c;其生成的图片效果可以与Midjourney、leonardo、ideogram等顶级产品媲美&#xff0c;随后被融合到ChatGPT中增强其…

matlab的歧视:simulink不能使用stm32f4系列的ADC?

2023b的matlab&#xff0c;stm32f407芯片&#xff0c;运行内容Using the Analog to Digital Converter Block to Support STMicroelectronics STM32 Processor Based Boards Using the Analog to Digital Converter Block to Support STMicroelectronics STM32 Processor Base…

基于SSM的社区疫情防控管理信息系统

目录 背景 技术简介 系统简介 界面预览 背景 随着时代的进步&#xff0c;计算机技术已经全方位地影响了社会的发展。随着居民生活质量的持续上升&#xff0c;人们对社区疫情防控管理信息系统的期望和要求也在同步增长。在社区疫情防控日益受到广泛关注的背景下&#xff0c…

【漏洞复现】通天星CMSV6车载主动安全监控云平台inspect_file接口处存在任意文件上传漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

电商技术揭秘一:电商架构设计与核心技术

文章目录 引言一、电商平台架构概述1.1 架构设计原则与架构类型选择1.2 传统电商平台架构与现代化架构趋势分析 二、高并发处理与负载均衡2.1 高并发访问特点分析与挑战2.2 负载均衡原理与算法选择 三、分布式数据库与缓存技术3.1 分布式数据库设计与一致性考量3.2 缓存策略与缓…

基于SpringBoot和Vue的金融融资管理系统的设计和实现【附源码】

1、系统演示视频&#xff08;演示视频&#xff09; 2、需要交流和学习请联系

vue弹出的添加信息组件中 el-radio 单选框无法点击问题

情景描述:在弹出的添加信息的组件中的form中有一个单选框,单选框无法进行点击切换 原因如下: 单选框要求有个默认值,因为添加和更新操作复用同一个组件,所以我在初始化时对相关进行了判定,如果为空则赋初始值 结果这样虽然实现了初始值的展示,但是就是如此造成了单选框的无法切…

代码随想录算法训练营第二十九天(回溯5)|491. 非递减子序列、46. 全排列、47. 全排列 II(JAVA)

文章目录 491. 非递减子序列解题思路源码 46. 全排列解题思路源码 47. 全排列 II解题思路源码 总结 491. 非递减子序列 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 …

前端返回 List<Map<String, Object>>中的vaue值里面包含一个Bigdecimal类型,序列化时小数点丢失,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

Linux 命令 top 详解

1 top命令介绍 Linux系统中&#xff0c;Top命令主要用于实时运行系统的监控&#xff0c;包括Linux内核管理的进程或者线程的资源占用情况。这个命令对所有正在运行的进程和系统负荷提供不断更新的概览信息&#xff0c;包括系统负载、CPU利用分布情况、内存使用、每个进程的内容…

PS从入门到精通视频各类教程整理全集,包含素材、作业等(7)

PS从入门到精通视频各类教程整理全集&#xff0c;包含素材、作业等 最新PS以及插件合集&#xff0c;可在我以往文章中找到 由于阿里云盘有分享次受限制和文件大小限制&#xff0c;今天先分享到这里&#xff0c;后续持续更新 PS敬伟01——90集等文件 https://www.alipan.com/s…

Golang | Leetcode Golang题解之第7题整数反转

题目&#xff1a; 题解&#xff1a; func reverse(x int) (rev int) {for x ! 0 {if rev < math.MinInt32/10 || rev > math.MaxInt32/10 {return 0}digit : x % 10x / 10rev rev*10 digit}return }

ETL工具-nifi干货系列 第八讲 处理器PutDatabaseRecord 写数据库(详细)

1、本节通过一个小例子来讲解下处理器PutDatabaseRecord&#xff0c;该处理器的作用是将数据写入数据库。 如下流程通过处理器GenerateFlowFile 生成数据&#xff0c;然后通过处理器JoltTransformJSON转换结构&#xff0c;最后通过处理器PutDatabaseRecord将数据写入数据库。如…

keepalived+LVS高可用部署

目录 一.两台设备&#xff08;2.130和2.133&#xff09;作为调度器&#xff0c;前主后备 1.部署keepalived 2.修改配置文件准备启动 3.配置keepalived的系统日志并启动 二.模拟调度器掉点和web服务进程丢失 1.调度器掉点 2.当类似于httpd这种网站服务掉点 三.以三种健康…

C++ 前K个高频单词的六种解法

目录 大堆 小堆 vectorsort vectorstable_sort multimap set/multiset 与GPT的对话 1.对于比较类型中 < 运算符重载的理解 2.map有稳定性的说法吗 ​编辑 3.为什么map和set类的仿函数后面要加const来修饰*this 5.关于名词的理解 6.匿名对象对类要求 7.map和set的…

新手使用GIT上传本地项目到Github(个人笔记)

亲测下面的文章很有用处。 1. 初次使用git上传代码到github远程仓库 - 知乎 (zhihu.com) 2. 使用Git时出现refusing to merge unrelated histories的解决办法 - 知乎

【大数据存储】实验五:Mapreduce

实验Mapreduce实例——排序&#xff08;补充程序&#xff09; 实验环境 Linux Ubuntu 16.04 jdk-8u191-linux-x64 hadoop-3.0.0 hadoop-eclipse-plugin-2.7.3.jar eclipse-java-juno-SR2-linux-gtk-x86_64 实验内容 在电商网站上&#xff0c;当我们进入某电商页面里浏览…

windows@软件显示模糊@屏幕显示器分辨率和精细度

文章目录 refsDPIPPIPPI (Pixels Per Inch)DPI (Dots Per Inch) 屏幕尺寸数windows中DPI设置对单个应用设置DPI兼容性设置使用系统全局设置 获取屏幕(监视器)信息&#x1f47a;获取监视器的型号pnp 监视器windows 获取屏幕分辨率 高分辨率屏幕高分辨率和高精细度屏幕&#x1f4…