C语言变量的定义和赋值

C语言通过变量为程序设计者提供了使用存储器的手段,每个变量代表不同的存储单元。

1 基本数据类型

C语言中基本的数据类型有:整数类型、浮点类型(小数);

1.1 整数类型

整数类型又分为:char、short、int、long、long long;
每种类型又分为:无符号(unsigned)类型和有符号(signed)类型;
变量在定义的时候默认是有符号的,如果想要定义成为无符号类型,需要在类型的前面加关键字 unsigned ,例如:定义一个无符号的int类型数据num

unsigned int num;

有符号数的最高位是符号位 0为正数、1为负数

1.1.1 char类型

char类型即字符类型,在内存中占用 1 个字节 8bit
变量的定义格式:

char ch; //定一个变量名为ch的char型变量;
scanf(“%c”, &ch);
printf(“%c”. ch);
输入输出时使用格式 %c

存储的数据范围:

无符号 :[0, 2^8 - 1]
有符号:[-2^7 , 2^ -1]

为了防止正负0的问题,计算机中存储的是数据的补码

00000000 为0的补码
10000000 规定为-128的补码

1.1.2 short类型

short类型的即短整型,也可写成short int num,在内存中占用 2 个字节 16bit
变量定义格式:

short num; //定一个变量名为num的short型变量;
//short int num; //
同上,和上面表达的意义相同
scanf(“%hd”, &num);
printf(“%hd\n”, num);
输入输出时使用格式 %hd

存储的数据范围:

无符号:[0 , 2^16-1]
有符号:[-2^15 , 2^15-1]

1.1.3 int类型

int类型变量在内存中占用 4 个字节 32bit
变量定义格式:

int num; //定义一个变量名为num的int型变量;
scanf(“%d”, &num);
printf(“%d”, num);
输入输出时使用格式 %d

存储的数据范围:

无符号:[0 , 2^32-1]
有符号:[-2^31 , 2^31-1]

1.1.4 long类型

long类型即长整型,也可写long int,在内存的占用的字节随操作系统的字长相同,在32位操作系统上和 int 一样、在64位操作系统上 和 long long 一样;
变量定义格式

long num; //定义一个变量名为num的long类型变量
//long int num; //同上,两个表达的意义相同
scanf(“%ld”, &num);
printf(“%ld\n”, num);
输入输出需要使用格式 %ld

1.1.5 long long类型

long long类型也可以写成 long long int ,在内存中占用 8 个字节 64bit
变量定义格式

long long num; //定义一个变量名为num的long long类型变量
//long long int num; //同上,两个表达的意义相同
scanf(“%lld”, &num);
printf(“%lld\n”, num);
输入输出需要使用格式 %lld

存储的数据范围:

无符号:[0 , 2^64-1]
有符号:[-2^63 , 2^63-1]

1.2 浮点类型(实型)

浮点类型也叫实型,用来存储小数的,有float类型和double类型;
浮点类型涉及到小数的二进制,存储的是一个近似值
float和double类型的存储格式比较麻烦,就不介绍了;

1.2.1 float类型

float类型,单精度浮点类型,在内存中占用 4 个字节;

1.2.2 double类型

double类型,双精度浮点类型,在内存中占用8个字节;

2 变量的作用域和生存周期

将变量占用存储空间的的时间称为变量的生存周期,将可以引用这个变量的的程序段落称为变量的作用域

2.1 变量的作用域

变量的作用域依赖于源代码中变量定义的位置。在C语言中,变量可以在3个位置对变量进行定义:函数外部、函数内部和复合语句中。

2.1.1 局部变量

在函数内部定义的变量,包括参数列表中定义的形式参数被称为局部变量
每个函数定义的变量,只有在函数被调用的时候才对其进行分配存储空间,当函数执行结束后,系统会马上将这些存储空间回收。所以在不同的函数之间可以定义相同的名称的变量,这是因为位于不同函数的变量对应不同的存储空间,实质上是完全无关的独立变量。

2.1.2 全局变量

在函数外部定义的变量称为全局变量,全局变量是程序源代码中都可以使用的变量。
全局变量的存储空间在程序开始执行的时候就分配好了,当程序执行结束后才会将这些存储空间进行回收。
注意:

因为全局变量是源文件中任意一个函数都可以访问到,可能被误操作,并且数据在使用时一般会遵守一定的逻辑和时序,因此可能导致开发者难以发现错误所在;我们要尽量少使用全局变量。
2.1.3 块变量

在复合语句中定义的变量称为块变量
块变量就是一种特殊的局部变量,程序中任何复合语句,都可以声明块变量,用于语句内部的计算。程序中除了此复合语句以外的其他部分都不允许访问该变量。

2.1.4 注意事项

对于不同作用域的变量,可以使用相同的名称;对于相同作用域的变量,不可以使用相同的名称。如果全部变量和局部变量使用了相同的名称,则全局变量在该局部变量的作用域中无效,也就无法访问。

int i;//局部变量i
for(int i= 0; i<10; i++){...}	//块变量i
两个 i 的作用域不同,所以可以使用相同的名称,在for循环体内使用的是块变量 i ,在 for 循环体外使用的是局部变量;

int i = 0; //局部变量 i
int i = 3; //局部变量 i
这样的两个 i 如果在同一个函数题内,那么这样不合法,不能使用两个相同名称的局部变量;

2.2 变量的生存周期

全局变量的生命周期是整个程序执行期间
局部便是的生命周期是函数执行期间
块变量的生命周期是复合语句的执行期间

3 初始化和赋初值

3.1 变量的初始化

变量的初始化是在变量定义的时候就对其进行赋初值
如:

int num =0; //定义一个变量名为num的int型变量,并对其赋值0

3.2 变量赋初值

在变量定义的时候没有对其进行赋值,而是在定义之后、使用之前对其进行第一次赋值
如:

int num;//定义一个变量名为num的int型变量
num = 0;//将num赋值为0

3.3 注意事项

1、变量在变量的在定义后未去其进行赋初值之前,里面存储的是一个随机数,也叫垃圾值;我们不能确定其中存储的数值到底是什么,所以在使用之前最好对其进行赋初值,要不影响计算结果;
2、变量未被定义则不能进行直接使用;

int p = q, q = 10;//先使用变量q,后定义,这样是违法的
int q = 10, p = q; //这样就合法了,因为在使用变量q的时候已经定义了
int a = b = c = 0;//这样定义也是违法的

4 变量的类型转换

变量的类型转换就是在某次运算中通过某种方式将变量的类型转换成新的类型,来参与本次运算。变量自身的类型不会发生概念。分为显试(强制)类型转换和隐试类型转换;

4.1 显试类型转换

显试类型转换是程序员个人所操作的;
格式:

(新的类型)变量名;
int m = 5, n = 2;
float ret1 = m/n; // ret1 = 2.000000
float ret2 = (float)m/(float)n; // ret2 = 2.500000

注意:

强制类型转换,是不安全的,要谨慎使用。
小的类型转大的类型一般没问题,
但是大的类型转小的类型就可能出现数据的截断和丢失。

char m = 100;
int n = (int)m;
printf("m = %d, n = %d\n", m, n);//100 100

int m = 100;
char n = (char)m;
printf("m = %d, n = %d\n", m, n);//100 100

int m = 300;
char n = (char)m;
printf("m = %d, n = %d\n", m, n);//300 44//数据被截断了

4.2 隐试类型转换

隐式强转是由编译器根据上下文自动推导而来的,如果编译器认为是安全的,则允许使用;如果编译器认为是不安全的,会报一个警告。具体取决于编译器的严谨程度。

float f = 3.14;
int m = f;//--隐式强转  相当于取整的操作
printf("m = %d  f = %f\n", m, f);//3 3.14

注意:

有符号数和无符号数参与运算时,会将有符号数强转成无符号数参与运算,结果也是一个无符号数。
下面的例子会输出yes

#include <stdio.h>

int main(int argc, const char *argv[])
{
	signed int a = -20;
	unsigned int b = 10;
	if( a+b > 0 ){
		printf("yes\n");
	}else{
		printf("no\n");
	}
	return 0;
}