C语言基础知识入门(二)
一、基本数据类型
C语言中,数据类型可分为:
- 基本数据类型
- 构造数据类型
- 指针类型
- 空类型四大类
基本类型:它们是算术类型,包括两种类型:整数类型(整型和字符型)和浮点类型。在C语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。
void类型:类型说明符void表明没有可用的值
派生类型:它们包括:指针类型、数组类型、结构类型、枚举类型、共用体类型和函数类型(数组类型和结构类型统称为聚合类型。函数的类型指的是函数返回值的类型,枚举类型被用来定义在程序中只能赋予其一定的离散整数值的变量)。
最常用的整型, 实型与字符型(char,int,float,double):
整型数据是指不带小数的数字(int,short int,long int, unsigned int, unsigned short int,unsigned long int):
注:
- int short int long int是根据编译环境的不同,所取范围不同。
- 而其中short int和long int至少是表中所写范围, 但是int在表中是以16位编译环境写的取值范围。
- 另外 c语言int的取值范围在于他占用的字节数 ,不同的编译器,规定是不一样。
- ANSI标准定义int是占2个字节,TC是按ANSI标准的,它的int是占2个字节的。但是在VC里,一个int是占4个字节的。
整数类型(字符型与整型)补充图表
类型 |
存储大小 byte(s) |
值范围 |
char |
1 |
-128到127或0到255 |
unsigned char |
1 |
0到255 |
signed char |
1 |
-128到127 |
int |
2或4 |
-32768到32767或-2147483648到2147483647 |
unsigned int |
2或4 |
0到65535或0到4294967295 |
short |
2 |
-32768到32767 |
unsigned short |
2 |
0到65535 |
long |
4 |
-2147483648到2147483647 |
unsigned long |
4 |
0到4294967295 |
二、浮点类型
浮点数据是指带小数的数字。
生活中有很多信息适合使用浮点型数据来表示,比如:人的体重(单位:公斤)、商品价格、圆周率等等。
因为精度的不同又分为3种(float,double,long double):
为了得到某个类型或某个变量在特定平台上的准确大小,可以使用sizeof运算符。表达式sizeof(type)得到对象或类型的存储字节大小。
- #include<stdio.h>
- int main(){
- printf("%d\n",sizeof(char));
- printf("%d\n",sizeof(int));
- printf("%d\n",sizeof(long));
- printf("%d\n",sizeof(float));
- printf("%d\n",sizeof(double));
- //"\n"是转义字符,表示换行
- /*
- “%d”表示按十进制整型输出
- “%f”表示按小数形式输出单、双精度实数
- “%c”表示按字符型输出
- */
- return 0;
- }
void类型
void类型指定没有可用的值。它通常用于以下三种情况:
1.函数返回为空
C中有各种函数都不返回值,或者可以说它们返回空。不返回值的函数的返回类型为空。
eg: void exit(int status);
2.函数参数为空
C中有各种函数不接受任何参数。不带参数的函数可以接受一个void
eg: int rand(void);
3.指针指向void
类型为void*的指针代表对象的地址,而不是类型。例如,内存分配函数void* malloc(size_t size);返回指向void的指针,可以转换为任何数据类型。
三、格式化输出语句
格式化输出语句,也可以说是占位输出,是将各种类型的数据按照格式化后的类型及指定的位置从计算机上显示。
其格式为:printf("输出格式符",输出项)
;
当输出语句中包含普通字符时,可以采用以下格式:
printf("普通字符输出格式符", 输出项);
注意:格式符的个数要与变量、常量或者表达式的个数一一对应
四、常量
在程序执行过程中,值不发生改变的量称为常量。
mtianyan: C语言的常量可以分为直接常量和符号常量。
直接常量也称为字面量,是可以直接拿来使用,无需说明的量,比如:
- 整型常量:13、0、-13;
- 实型常量:13.33、-24.4;
- 字符常量:‘a’、‘M’
- 字符串常量:”I love imooc!”
在C语言中,可以用一个标识符来表示一个常量,称之为符号常量。符号常量在使用之前必须先定义,其一般形式为:
#define 标识符 常量值
#include <stdio.h>
#define POCKETMONEY 10 //定义常量及常量值
int main()
{
// POCKETMONEY = 12; //小明私自增加零花钱对吗?
printf("小明今天又得到%d元零花钱\n", POCKETMONEY);
return 0;
}
符号常量不可以被改变。
五、变量
变量就是可以变化的量,而每个变量都会有一个名字(标识符)。变量占据内存中一定的存储单元。使用变量之前必须先定义变量。
变量定义的一般形式为:数据类型 变量名;
多个类型相同的变量:数据类型 变量名1, 变量名2, 变量名3…;
变量的赋值分为两种方式:
- 先声明再赋值
- 声明的同时赋值(初始化)
不带初始化的定义:带有静态存储持续时间的变量会被隐式初始化为NULL(所有字节的值都是0),其他所有变量的初始值是未定义的。
- #include<stdio.h>
- int main(){
- int a;
- a=10;
- int b=20;
- float d1,d2,d3;
- d1=1.1;
- d2=2.2;
- d3=3.3;
- printf("%d\n%d\n%f\n%f\n%f\n",a,b,d1,d2,d3);
- return 0;
- }
变量的作用域
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
- 局部变量的作用域是变量所在的局部范围。(就是大括号里边的变量只能在大括号里用)
- 全局变量的作用域是整个工程。(就是大括号外边的变量在哪都能用)
变量的生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。(大括号大括号!)
- 全局变量的生命周期是:整个程序的生命周期。 (在哪都行!)
注:后面的存储类也会涉及到。
上面的代码中"int b=20;" "="是赋值运算符,在这里表示把20赋值给b,那么为什么不能写成“int 20=b;”呢?
左值和右值
C中有两种类型的表达式:
左值(lvalue):指向内存位置的表达式被称为左值表达式。左值可以出现在赋值号的左边或右边。
右值(rvalue):术语右值指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,因此不能被赋值,不能出现在赋值号的左边。
了解了以上这些之后我们就可以实现加法啦!
比如我们想计算456+789的和
- #include<stdio.h>
- int main(){
- int a=456;
- int b=789;
- int c=a+b;
- printf("%d\n",c);
- return 0;
- }
这样我们就可以实现啦!
有的小伙伴此时可能会问,计算不同的值每次需要改a和b的值,那能不能从键盘输入数去计算呢?
这也是可以的,有请我们的 scanf 出场
- #include<stdio.h>
- int main(){
- int a;
- int b;
- scanf("%d %d",&a,&b);
- int c=a+b;
- printf("%d\n",c);
- return 0;
- }
scanf函数是格式化输入函数,用于接受从键盘输入的数据,用户输入数据完成后,按回车键(Enter)结束输入。格式和printf类似,多一个“&”。
printf和scanf函数的具体用法后续会补充。
实现加法了,那减法和乘法只需要改个符号就可以了,注意,乘法符号是“ * “。那除法(符号是" / ")呢?为什么我没说,是有什么不一样吗?
如果是沿用上面的456/789,你会发现结果是0。
而1/2是0 5/2是2 -7/3是-2 -8/-3是2
这是因为C语言使用向零取整方式
在C语言中规定,两个整数相除,如果不能整除,那么结果的小数部分的处理应该向0靠近;如果两个异号整数进行取模运算,那么结果的符号应该与被除数相同。
取模运算
取模运算也叫取余运算,在C中用%来表示, 数学中叫mod。 x mod y = x%y
x%y = x - y[x/y], for y!=0.
数学中的余数概念和我们的计算机中的余数概念一致,但实现却不一致。 其中 [x/y] 代表的是 x/y 的最小下界。
类型转换
自动类型转换
将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,在编译的时候自动完成,不需要程序员干预。
自动类型转换有以下几个规则:
- 字节小(级别低)的可以向字节大(级别高)的自动转换,但字节大的不能向字节小的自动转换
- 无符号类型级别高于有符号类型(unsigned > signed)
- 浮点型级别高于有符号、无符号整型(与浮点运算,结果都为浮点型)
- 双精度浮点级别高于单精度浮点(double > float)
- #include <stdio.h>
- int main(){
- float PI = 3.14159;
- int r = 5;
- int s1;
- double s2;
- s1 = r*r*PI; //s1=78
- /*
- 在计算表达式r*r*PI时,r和PI都被转换成 double 类型,
- 表达式的结果也是 double 类型。
- 但由于 s1 为整型,所以赋值运算的结果仍为整型,
- 舍去了小数部分,导致数据失真。
- */
- s2 = r*r*PI; //s2=78.539749
- printf("s1=%d s2=%f\n", s1, s2);
- return 0;
- }
强制类型转换
格式为:(type_name) expression
(数据类型) 表达式
其作用是把表达式的运算结果强制转换成类型说明符所表示的类型
在使用强制转换时应注意以下问题:
- 数据类型和表达式都必须加括号, 如把(int)(x/2+y)写成(int)x/2+y则成了把x转换成int型之后再除2再与y相加了。
- 转换后不会改变原数据的类型及变量值,只在本次运算中临时性转换。
- #include <stdio.h>
- int main(){
- float x=1.5f,y=2.0f;
- //小数后加f,表示这个小数是float类型数据
- printf("%d\n",(int)(x+y));
- //强制转换的是表达式的值,x自身是不变的
- printf("x=%f\n",x);//x=1.500000
- printf("%d\n",(int)(x));
- printf("x=%f\n",x);//x=1.500000
- return 0;
- }
在C语言中,有些类型既可以自动转换,也可以强制转换,例如 int 到 double,float 到 int 等;而有些类型只能强制转换,不能自动转换,例如以后将要学到的 void * 到 int *,int 到 char * 等。 可以自动转换的类型一定能够强制转换,但是,需要强制转换的类型不一定能够自动转换。
可以自动进行的类型转换一般风险较低,不会对程序带来严重的后果,例如,int 到 double 没有什么缺点,float 到 int 顶多是数值失真。只能强制进行的类型转换一般风险较高,或者行为匪夷所思,例如,char * 到 int * 就是很奇怪的一种转换,这会导致取得的值也很奇怪,再如,int 到 char * 就是风险极高的一种转换,一般会导致程序崩溃。