学习博客上的各种杂知识 兜兜转载
((condition)?a:b) = complicated_expression;
不能,?:操作符跟多数操作符一样,可以生成一个值,而不是被赋值,换言之,?:不能生成一个左值。如果真的需要,可以
*((condition)?&a:&b) = complicated_expression;
.宏扩展必须使用括号,以便保护表达式中低优先级的操作符
#define
square(x) ((x) * (x))
square(x) ((x) * (x))
有人说不能在printf中使用%lf,为什么printf中用%f输出double型,而scanf却用%lf呢?
printf的%f说明符既可以输出float型又可以输出double型。根据默认参数提升规则,float型会被提升为double型,因此
printf只会看到双精度数。
独有scanf,情况就完全不一样了,它接收指针,这里没有类似的类型提升,向float存储和向double存储大小不一样,因此
scanf区分%f和%lf。
可以使用sscanf,例如123ABC5.678,可以用”%d%3s%f“读取。
- sscanf(str,"%d%3s%f",&i,s,&f);
-
printf("%d,%s,%f\n",i,s,f);
C基础数据类型
1.int 4字节
2.char 1字节
3.float 4字节
4.double 8字节
5.bool 1字节
某种规则便是C语言内存管理机制。
1.分区
代码区 |
静态区 |
堆 |
空闲内存 |
栈 |
明确的分区是管理的前提,只有我们确定了房间分那几块区域,才能确定下一步区域摆放哪些物品。确定分区后,我们需要一份清单,记录分类摆放的规则:
1.代码区:存放程序执行的代码
2.静态区:全局变量和静态变量(有的同学可能有更深的认识静态区可以 细分为:
1.非初始化数据段:存放未初始化的全局变量和静态变量。
2. 初始化的数据:存放初始化的全局变量和静态变量。)
3.堆:动态分配区域,malloc, calloc, realloc等函数
4.空闲内存:堆栈式可延伸的,空闲内存提供堆向下与栈向上需要的空间
5.栈:局部变量及每次函数调用时返回地址、以及调用者的环境信息
C语言设计了这个规则,并严格的为每个程序分配与管理内存,使程序的运行井然有序。一个物品摆放整齐的房间,寻找某件物品会更快,C语言的内存分配机制同样如此,使其拥有更优良的性能。
指针:指针指向一块内存空间。
2.指针的操作
& ;取址运算符,借助&可以让指针指向特定变量的内存地址。
* ;间接访问运算符,借助*可以间接地把指针指向地址里的内容取出来。
+/-;加减运算符
3.指针的诱人之处
3.1高效的参数传递:函数参数的传递,一般是以实参复制给形参的方式实现,如果参数很大复制 过程巨大的消耗将让人难以接受,这时选择用指针传递参数的地址(地址大小是固定的)具有无可比拟的优势。
3.2动态内存分配支持:内存动态分配的实现依赖于指针,将动态开辟的地址赋给指针,通过指针对分配的内存进行访问,同样通过指针实现内存的释放回收。
3.3对链表的支持:链表是一种重要的数据管理结构,具有十分优秀的性能,应用十分广泛。指针的支持是链表能将不连续内存地址形成链的关键,指针就没有链表。
4.指针的隐患
4.1指针未初始化;在C中并不对指针指向空间的内容进行检查,如果指针没有初始化,对该指针的使用将导致不可预测的结果。
4.2局部变量地址被回收引起异常:指针指向一个局部变量的地址,在局部变量生存期结束时系统将自动收回其内存空间,此时指针便指向一个不存在的空间。在两个指针指向同一个地址空间时,其中一个释放将会导致另一个指针置空。
4.3指针改变引起的内存泄漏: