1、数据类型
1.1 基本数据类型
数据类型分2类:基本数据类型+复合类型
基本类型:char short int long float double
复合类型:数组 结构体 共用体 类(c++)
1.1.1内存占用与sizeof运算符
数据类型就好像一个个的模子,这个模子实例化出C语言的变量。变量存储在内存中,需要占用一定的内存空间。一个变量占用多少空间由变量的数据类型决定的。
每种数据类型,在不同的机器平台上占用内存是不同的。我们一般讲的时候都是以32位CPU为默认的硬件平台来描述:
char 1字节 short 2 int 4 long 8 float 4 double 8
1.1.2 有符号数和无符号数
对于char short int long 等整型类型的数,都分有符号数和无符号数。而对于float和double这种浮点型数来说,只有有符号数,没有无符号数。
1.1.3 整型数和浮点型数存储方式上的不同
对于C语言来说,数(变量)是存储在内存中一个个的格子中的。存储的时候是以二进制方式存储的,对于有符号数和无符号数来说,存储方式是不同的。譬如对于int来说
unsigned int无符号数,32位全部用来存数的内容,所以表示的数的范围是0-4294967295(2^32-1)
int 有符号数,32位中最高位用来存符号(0表示正数,1表示负数),剩余的31位用来存数据。所以可以表示的范围-2^31 ~ 2^31-1
结论:从绝对数值来说,无符号数所表示的范围要大一点。
对于float和double这种浮点类型的数,它在内存中的存储方式和整型数不一样。所以float和int相比,虽然都是4个字节但是在内存中存储的方式完全不同。所以同一个4字节的内存,如果存储时是按照int存放的,取的时候一定要按照int型方式去取。
总结:存取方式上主要有两种,一种是整型一种是浮点型,这两种存取方式完全不同,没有任何关联,所以是绝对不能随意改变一个变量的存取方式。在整型和浮点型之内,譬如说4中整型char、short、int、long只是范围大小不同而已,存储方式是一模一样的。float和double存储原理是相同的,方式上有差异,导致了能表示的浮点型的范围和精度不同。
1.2 空类型(关键字void)
C语言中的void类型,代表任意类型,而不是空的意思。任意类型的意思不是说想变成谁就变成谁,而是说它的类型是未知的,是还没指定的。
void * 是void类型的指针。含义是:这是一个指针变量,该指针指向一个void类型的数。void类型的数就是说这个数有可能是int,有可能是float,也有可能是个结构体,那种类型都有可能,只是我当前不知道。
void型指针的作用就是,程序不知道那个变量的类型,但是程序员自己心里知道。程序员如何知道?当时给这个变量赋值的时候是什么类型,现在取的时候就是什么类型。这些类型对不对,能否兼容,完全由程序员自己负责。编译器看到void就没办法帮你做类型检查了。
在函数的参数列表和返回值中,void代表的含义是:一个函数形参列表为void,表示这个函数调用时不需要给它传参的。返回值类型是void,表示这个函数不会返回一个有意义的返回值。所以调用者也不要想着去使用该返回值。
C语言设计基本理念:
C语言相信程序员永远是对的,C语言相信程序员都是高手,C语言赋予了程序员最大的权利。所以C语言的程序员必须自己对程序的对错负责,必须随时脑袋清楚,知道自己在干嘛。
#include <stdio.h>
int main(void)
{
int a = 444;
void *pvoid;
pvoid=&a;
printf("*pvoid=%d.
*pvoid=%f.
",*(int *)pvoid,*(float *)pvoid);
//在这里由于编译器不知道pvoid是什么类型的指针,所以我们在用的时候强制他用int *类型
//第二个强制用float *,编译器是不会报错的,他不知道,但取出来是错的。
return 0;
}
1.3 数据类型的转换
C语言中有各种数据类型,写程序时需要定义各种类型的变量,这些变量需要参与运算。C语言有一个基本要求就是:不同类型的变量是不能直接运算的。就是说,int和float类型的变量不能直接加减乘除,必须先把两种类型专程相同的类型才可以。
1.3.1 隐式转换
就是自动转换,是C语言默认会进行的,不用程序员干涉。
C语言理念:隐式类型转换默认朝精度更高、范围更大的方向转换。
1.3.2 强制转换
C语言默认不会这么做,但程序员我想这么做。
1.4 C语言与bool类型(只有两个值0,1,就是真和假)
C语言中原生类型没有bool,C++中有。在C语言中如果需要使用bool类型,可以用int来代替。
2、变量和常量
2.1、变量
2.1.1、局部变量
定义在函数内部的变量
2.1.1.1、普通局部变量auto
2.1.1.2、静态局部变量static
2.1.1.3、寄存器局部变量register
一般只在内核或者启动代码中,需要反复使用同一个变量这种情况下才会使用
2.1.2、全局变量
定义在函数外面的变量
2.1.2.1、普通全局变量
2.1.2.2、静态全局变量(屏蔽作用,单个源文件独用)
2.1.2.3、跨文件引用全局变量extern
对比:
1、定义同时没有初始化,则局部变量的值是随机的,而全局变量的值默认为0。
2、使用范围上:全局变量具有文件作用域(文件范围内,定义位置之后有效),而局部变量只有代码块作用域。代码块就是用{}扩起来的一段代码。
3、变量的分配位置:全局变量分配在数据段上,而局部变量分配在栈上。
数据段:数据段存的是数,像全局变量就是存在数据段的。
代码段:存的是程序代码,一般是只读的。
栈stack:先进后出。C语言中局部变量就分配在栈中。程序运行时,局部变量放入栈中,各个局部变量和栈中的地址相关联就是局部变量的诞生,出了代码块,变量地址释放,变量就死了。
插一段LINUX GCC使用。
多文件C语言项目
1、简单的C语言程序只有一个C文件a.c,编译的时候gcc a.c -o a
2、复杂的C语言程序是由多个C文件构成的。譬如一个程序中有2个c文件,编译的时候gcc a.c b.c -o ab