C学习笔记(1)---数据类型,变量,储存类
1.常用基本数据类型占用空间(64位机器为例):
char : 1个字节 -- int :4个字节 -- float:4个字节 -- double:8个字节
2.书写类型:
a.整数: a. 默认为10进制 ,10 ,20. - b. 以0开头为8进制,045,021. - c.以0b开头为2进制,0b11101101. - . d.以0x开头为16进制,0x21458adf.
b. 浮点:a. float 4 字节 byte - b.double 8 byte -c. long double 16 byte
c.字符型常量
char 用英文单引号括起来,只保存一个字符'a'、'b' 、'*' ,还有转义字符 '\n' 、'\t'。
d.字符串常量
用英文的双引号引起来 可以保存多个字符:"abc"。
3.变量声明
a、一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。
b、另一种是不需要建立存储空间的,通过使用extern关键字声明变量名而不定义它。 例如:extern int a 其中变量 a 可以在别的文件中定义的。除非有extern关键字,否则都是变量的定义。
c. #define 是宏定义,它不能定义常量,但宏定义可以实现在字面意义上和其它定义常量相同的功能,本质的区别就在于 #define 不为宏名分配内存,而 const 也不为常量分配内存,怎么回事呢,其实 const 并不是去定义一个常量,而是去改变一个变量的存储类,把该变量所占的内存变为只读!
------------------------------------------------------------------------
sub:
const 定义的是变量不是常量,只是这个变量的值不允许改变是常变量!带有类型。编译运行的时候起作用存在类型检查。
define 定义的是不带类型的常数,只进行简单的字符替换。在预编译的时候起作用,不存在类型检查。
1、两者的区别
(1) 编译器处理方式不同
- #define 宏是在预处理阶段展开。
- const 常量是编译运行阶段使用。
(2) 类型和安全检查不同
- #define 宏没有类型,不做任何类型检查,仅仅是展开。
- const 常量有具体的类型,在编译阶段会执行类型检查。
(3) 存储方式不同
- #define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。(宏定义不分配内存,变量定义分配内存。)
- const常量会在内存中分配(可以是堆中也可以是栈中)。
(4) const 可以节省空间,避免不必要的内存分配。 例如:
#define num 3.14159 //常量宏 const doulbe num = 3.14159; //此时并未将pi放入rom中 ...... double i = num; //此时为pi分配内存,以后不再分配! double i= num; //编译期间进行宏替换,分配内存 double j = num; //没有内存分配 double j = num; //再进行宏替换,又一次分配内存!
const 定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象 #define 一样给出的是立即数,所以,const 定义的常量在程序运行过程中只有一份拷贝(因为是全局的只读变量,存在静态区),而 #define 定义的常量在内存中有若干个拷贝。
(5) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
(6) 宏替换只作替换,不做计算,不做表达式求解;
宏预编译时就替换了,程序运行时,并不分配内存。
----------------------------------
d.
define 注意“边缘效应”,例:#define n 2+3, n 的值是 5。
int a = n/2
在编译时我们预想 a=2.5,实际打印结果是 3.5 原因是在预处理阶段,编译器将 a=n/2 处理成 a=2+3/2,这就是 define 宏的边缘效应,所以我们应该写成 #define n (2+3)。
4.储存类:
auto 是局部变量的默认存储类, 限定变量只能在函数内部使用;
register 代表了寄存器变量,不在内存中使用; sub: register用于定义存储在寄存器中而不是 ram 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 '&' 运算符(因为它没有内存位置)。
static是全局变量的默认存储类,表示变量在程序生命周期内可见; sub:
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中。
extern 表示全局变量,即对程序内所有文件可见,类似于java中的public关键字
sub:
extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 extern 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。
引用:1.菜鸟教程:
2. 评论区笔记