C:入门级积累(4)


(int *)malloc(10 * sizeof(int))memory allocate动态分配内存,malloc的出现时为了弥补静态内存分配的缺点,传统数组的长度一旦定义之后,就不能更改,比如说,如果我有一个业务在这之前给分配的大小为100,但是,我现在由于业务数量的增长,原来的大小就无法满足。静态分配不能跨函数调用,就是无法在另一个函数中,来管理一个函数中的内存。静态分配,只在当前函数有效,当静态分配所在的函数运行完之后,该变量就不能被其他的函数所调用。
加(int *)的目的是让计算机知道,如何去划分这个开辟的空间,因为char,int,long这些类型的字节大小是不一样的,我们知道了
首地址,还要知道是以几个字节为单元。所以这句话一共开辟了10*8个字节,这也就是为什么写sizeof(int)的原因,因为指针变量的长度是跟随计算机走的
void free(void *)C语言中释放内存空间的函数,通常与申请内粗空间的函数malloc结合使用,可以释放由malloc,calloc,realloc。ptr指针指向一个要释放的内存的内存块,该内存块之前是通过调用上述三个函数进行分配的。如果传递的参数是一个空指针,则不会执行任何动作。
void* calloc(size_t num ,size_t size)calloc函数也是与free函数配套使用的,使用方式与malloc基本相同,也是在堆区中申请动态内存空间,头文件为stdlib.h,返回类型为空指针,size_t num 为元素个数,size_t size为每个元素的字节大小,与malloc的区别,参数使用方式不同。malloc的使用效率较高,因为calloc在返回在堆区中申请的那块动态内存的起始之前---https://blog.csdn.net/weixin_63449996/article/details/124363422
realloc
内存重叠
静态分配的变量在函数执行完毕之后自动,该内存会自动释放。静态分配的内存,是在栈中分配的。传统数组(静态分配),不能手动释放,只能等待系统释放。
https://blog.csdn.net/sinat_29957455/article/details/60883355
动态分配的变量动态分配通过malloc分配,是在堆中分配的,对不是一种数据结构,它是一种排序方式,堆排序
https://blog.csdn.net/sinat_29957455/article/details/60883355
extern void* memset(
  void* __s,
  int __c,
  size_t __n)
memset(rstar, 0x00,sizeof(int)*10);
sizeof()
条件编译器#if #ifdef #ifndef,#endif,#else,#elif条件编译(condition compiling)命令指定预处理器依据特定的条件来判断保留或删除某段源代码,例如可以使用条件编译让源代码适用于不同的目标系统,而不需要管理该源代码的各种不同版本,预处理器会依次计算条件表达式,直到发现结果非0(也就是true)的条件表达式,预处理器会保留对应组内的源代码。一共后续处理,如果找不到值为true的表达式,并且该条件编译区域中包含#else命令,则保留#else命令内的代码。在预处理阶段结束时,没有被预处理器保留以用于后续处理的组会从程序中全部删掉。http://c.biancheng.net/view/449.html
defined
#define简单的宏定义:#define 标识符 替换列表(替换列表可以是数,字符串字面量,标点符号,运算符,标识符,关键字,字符常量,注意替换列表是可以为空的)
#undef取消某个宏定义
_Thread_local(C11新增)语义上就是线程的私有变量._Thread_local是新的存储类修饰符, 限定了变量不能在多线程之间共享。https://c.tedu.cn/notes/221985.html
线程存储类说明符。https://m.php.cn/manual/view/34232.html
_Static_assert(C11新增)编译器期间断言,当#if #error 预编译之后,编译器断言,assert是运行时断言,用的时候看具体的需求:https://c.tedu.cn/notes/221985.html
_Noreturn(C11新增)修饰函数句对不会有返回值,_Noreturn 声明的函数不会返回。引入此新的函数修饰符有两个目的:消除编译器对没有return的函数的警告,允许某种只针对不返回函数的优化:https://c.tedu.cn/notes/221985.html
_Generic(C11新增)C的泛型机制,高级函数宏:https://c.tedu.cn/notes/221985.html
_Generic ( assignment-expression , generic-assoc-list )
assignment-expression:赋值表达式,既传入_Generic函数的变量
generic-assoc-list:对赋值表达式产生的结果变量进行类型判断,并执行对此结果变量的执行函数
_Generic(a + 0.1f, int : b, float : c, default : b)++;
以上表达式:输入第一个参数为:a+0.1f  输出结果类型为浮点型,由于结果变量为float类型,将执行float:c这个类型和执行函数对,假设c值为2,最终c值输出为3
更过请参考:https://blog.csdn.net/qq_31243065/article/details/80904613
如果是switch case 是值判断,那么_Generic就是类型判断,执行对应的函数操作
_Atomic(C11新增)原子操作,原子锁:https://c.tedu.cn/notes/221985.html
c语言新增的类型限定符,不过编译器必须支持这一新特性
并发程序设计把程序执行分成可以同时执行的多个线程,这程序设计带来了新的挑战,包括如何管理访问相同数据的不同线程。C11通过包含可选的头文件stdatomic.h和thread.h,提供了一些可选的不是必须实现的管理办法,值得注意的是,要通过各种宏函数访问原子类型。当一个线程对一个原子类型的对象执行原子操作时,其他线程不能访问该对象。
所谓原子操作,就是该操作绝对不会在执行完毕前被任何其他事务或事件打断,也就是说,它的最小的执行单位,不可能有比它更小的执行单位,因此智利的原子实际是使用了物理学里面物质微粒的概念。
所以这里所说的原子操作,基本都包含我们三个方面所关心的语义:
Atomicity:操作本身是不可分割的
Visibility:一个线程对某个数据的操作何时对另外一个线程可见
Ordering:执行的顺序是否可以被重排
这有点类似互斥对象对共享资源的保护,但是原子操作更加接近底层,因为效率更高
参考:https://blog.csdn.net/Galaxy_Robot/article/details/106991200
ATOMIC_VAR_INIT(value) (value)(自C11以来)初始化一个新的atomic_flag(宏常量)
扩展为一个表达式,可以用来初始化一个与之类型相同的原子变量value。未使用此初始化的自动存储持续时间的源自对象的初始值未定义,但是,静态和线程局部变量的默认(零)初始化会生成有效值
如果这个宏不用于初始化一个原子变量,那么在从另一个线程初始化(即使通过一个原子操作)期间,任何访问数据竞争(如果地址通过memory_order_relaxed操作立即传递给另一个线程,则可能发生):https://m.php.cn/manual/view/34183.html
原子操作原子操作指的是对原子对象的读和写是不可被打断的,一个操作不可被打断意味着在执行整个操作过程中,即使有一个硬件中断信号过来,该中断信号也不能立即触发处理器的中断执行例程处理器必须执行完整条原子操作之后才可以进入中断执行例程
对于来自多个处理器核心对同一个存储空间的访问,存储器控制器回去仲裁当前那个原子操作先进行方寸操作,哪个后执行,这些访存操作都会被串行化
所以原子对象往往用于多核多线程并行计算中对多个线程共享变量的计算
参考:https://www.jianshu.com/p/606c4f2bae52
原子类型用_Atomic(类型名) 这种方式修饰的类型是原子类型,在实际使用原子类型时应当避免直接使用_Atomic (类型名)这种形式,而是直接用<stdatomic.h>头文件中已经定义好的原子类型。此外该头文件还有相应的原子操作函数。
参考:https://www.jianshu.com/p/606c4f2bae52
原子函数c语言中的原子操作是指在执行期间不会被中断的操作,这种操作通常用于多线程编程,以确保线程安全和数据的一致性。在C语言中原子操作可以通过使用特殊的函数来实现。C语言中的原子操作函数通常以atomic_开头。这些函数可以用于执行各种原子操作,例如读取和写入变量,增加和减少变量的值等。以下是一些常用的原子操作:
1.atomic_load:用于读取变量的值,并确保在读取期间不会被其他线程修改
2.atomic_store:用于将值写入变量,并确保写入期间不会被其他线程修改
3.atomic_add:用于将一个值加到变量中,并确保在加法期间不会被其他线程修改
4.atomic_sub:用于将一个值从变量中减去,并确保在减法期间不会被其它线程修改
5.atomic_exchange:用于交换两个变量的值,并确保在期间不会被其它线程修改
6.atomic_compare_exchange:用于比较两个变量的值,并在它们相等时将一个新值写入其中一个变量。这个操作可用于实现比较并交换
使用原子操作可以避免多线程编程中的静态条件和死锁问题,例如,如果两个线程同时尝试写入同一个变量那么可能会发生竞态条件,导致变量的值不确定。但是,如果使用原子操作来执行写入操作,那么只有一个线程能够成功的写入变量,从而避免了竞态条件
原子操作还可以用于实现锁和信号量等同步机制。例如,可以使用原子操作来实现一个简单的自旋锁。
参考https://wenku.baidu.com/view/a10982e987868762caaedd3383c4bb4cf7ecb783.html

tips: 你错过了那么可爱善良温柔漂亮性感聪明活好的女朋友,我要是你,我就选择自杀。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千码君2016

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值