声明,定义和初始化
声明标识符iden是告诉编译器"有这么一个变量var,具体var里是什么,你自己去看"。声明只需要标识符的类型和标识符名字,C语言的任何标识符在使用前都需要声明,当然变量也不例外;如果标识符的定义代码在使用之前,那么定义的代码可以看作是声明,否则需要声明
定义标识符iden是告诉编译器"这个iden是什么";
初始化标识符iden是定义iden时给iden赋值,一个没有被赋值的iden里面存的是之前这块内存的值,就可能是任意的值,一不小心使用这样的标识符是十分危险的,所以一个好的习惯是定义一个标识符后立即初始化;另外一个原因是常量的值必须在初始化时确定,如果不进行初始化,那么这个常量以后永远都不能赋值了
通常情况下,当我们写int atom=10;
时,就同时进行了变量的定义和初始化。
指针
- 内存就是一排大小都是一byte,且自己编号的抽屉。编号即抽屉的地址,里面的东西即抽屉的内容
- 指针即"地址"。即抽屉的编号
- 指针变量即存储"标识符地址"的变量,即存放了另一个抽屉编号的抽屉,对指针变量"取值"即得到标识符的地址,即"指针的指向",对该变量"取址"即该变量本身存放的地址。当提及指针的时候,一定要注意说的是一个指针常量(一个地址), 还是一个指针变量,这是国内的教材非常差劲的一个习惯
- 一个指针变量理论上可以存储任何标识符的地址,但是为了便于管理,C语言把指针变量也按照标识符的类型进行了划分。所以有了函数的指针,字符指针,数组指针etc. 但他们其实都一样,即虽然所有的抽屉的编号都是一张纸条,但某个抽屉只用来存储装了苹果的抽屉的编号,另一个抽屉只用来存储装了橘子的抽屉的编号。
定义并初始化一个指针变量,由于运算符优先级的问题,并没有固定的定义格式,基本上每种不同的标识符都有自己的指针定义格式
int* pVar=&var; //数据类型指针变量
char (*ptr)[3]={'a','b','c'}; //数组指针变量,本质是指针,指向一个数组 VS char* str[10]={"this","is","a","string"};指针数组,本质是数组,每个元素都是一个指针
int (*pFcn)(int x)=fcn; //函数指针变量,指向一个函数的地址,函数名就是一个指针
使用指针
int var2=*pVar;//取值
int** ppVar=*pVar;//取址,这里定义一个指向指针的指针变量
指针常量VS常量指针
指针常量const int* ptr
表示不能通过指针修改指向的变量的内容
常量指针int* const ptr
表示指针的指向不能改变。
基本数据类型char int etc.
基本数据类型是C语言规定好的数据类型,它们占据内存的大小,对该块内存的使用方式都是编译器规定好的,我们只能使用,不能更改。
在一个典型的32位操作系统中:
数据类型 | 占位符 | 长度 | 数值范围(指数表示) | 数值范围(数字表示) |
---|---|---|---|---|
char | %c | 1 | -2^7~2^7-1 | -128~127 |
unsigned char | %c | 1 | 0~2^8-1 | 0~255 |
short | %hd | 2 | -2^15~2^15-1 | -32768~32767 |
unsigned short | %hu | 2 | 0~2^16-1 | 0~65535 |
int | %d | 4 | -2^31~2^31-1 | -2147483648~2147483647 |
unsigned int | %u | 4 | 0~2^32-1 | 0~4294967295 |
long | %ld | 4 | -2^31~2^31-1 | -2147483648~2147483647 |
unsigned long | %lu | 4 | 0~2^32-1 | 0~4294967295 |
float | %f或%g | 4 | ||
double | %lf或%lg | 8 |
Note:
- %f和%lf会保留小数点后多余的0(就算你写的5.2,也会输出5.200000),而%g和%lg不会保留哪些0
- 不同平台(eg:32位VS64位系统)数据类型的长度会有不同,具体需要用sizeof测,上表针对一般32位系统,以int为例,一个int占4byte,一个byte占8位,所以一个int由32位二进制表示,故int共能表示2^32个数
- float和double的范围是由指数的位数来决定的。float的指数位有8位,而double的指数位有11位,分布如下:
float: 1bit(符号位) 8bits(指数位) 23bits(尾数位)
double: 1bit(符号位) 11bits(指数位) 52bits(尾数位)
So,float的指数范围为-127~+128,而double的指数范围为-1023~+1024,并且指数位是按补码的形式来划分的。其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。
float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;
double的范围为-2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308 - 有符号的数据类型不是分“正数” 和 “负数”,而是 “非负数” 和 “负数”,其中的区别在于 0 是非负数里的,所以,只需要记住有多少个和有无符号就可以计算其范围
基本数据类型与指针
int var=10;
int* pVar = &var; //定义并声明一个指向int类型变量的一个指针,并将其指向var
int res=*pVar; //对一个指针取值
int* pTest=pVar;
字符串
C语言中的字符串用"有效字符"
来表示。
C编译器会自动在有效字符之后再加一个