数据类型
变量和常量
初始化
在定义变量的同时赋值,称之为“初始化”。
常量
常量的2种定义方式:
1、关键字const
const 数据类型 常量名 = 值;
如:const float pi = 3.14159;
2、宏定义
#define 常量名 值
PS: 这里没有"=“和”;"
如:#define PI 3.14159
推荐用宏定义的方式定义常量。
整形
进制
八进制:以数字0开始表明该数字是八进制。如:012表示八进制的12。
十六进制:以“0x”或“0X”开头表明该数字是十六进制。如:0xabc、0Xabc、0xABC、0XABC,这四个是同一个数字。
不能直接书写二进制。
所谓的“进制”,其实就是数字的不同格式。可以以不同的格式对整形变量赋值,也可以将整形变量输出成不同格式。
进制转换
整形的输入
VS的C4996提示
由于微软在VS2013中不建议再使用C的传统库函数scanf,strcpy,sprintf等,所以直接使用这些库函数会提示C4996错误:
VS建议采用带_s的函数,如scanf_s、strcpy_s,但这些并不是标准C函数。
要想继续使用此函数,需要在源文件中添加以下指令就可以避免这个错误提示:
#define _CRT_SECURE_NO_WARNINGS //这个宏定义最好要放到.c文件的第一行
#pragma warning(disable:4996) //或者使用这个
取地址运算符
&
为取地址运算符,使用方式为&变量名
。
int a;
//将输入的值存入变量a的地址中
scanf("%d", &a);
有符号数和无符号数的区别
有符号数:最高位为符号位,0代表正数,1代表负数。
无符号数:最高位不是符号位,而就是数的一部分,无符号数不可能是负数。
当我们写程序要处理一个不可能出现负值的时候,一般用无符号数,这样可以增大数的表达最大值。
sizeof关键字
- sizeof不是函数,所以不需要包含任何头文件,它的功能是计算一个数据类型在内存中占的字节大小
- sizeof的返回值为size_t
- size_t类型在32位操作系统下是unsigned int,是一个无符号的整数
sizeof的使用方法
1、用于数据类型
sizeof使用形式: sizeof(type)
数据类型必须用括号括住: sizeof(int)
2、用于变量
sizeof使用形式: sizeof(var_name) 或 sizeof var_name
变量名可以不用括号括住.如sizeof (var_name),sizeof var_name等都是正确形式
带括号的用法更普遍,大多数程序员采用这种形式。
#include<stdio.h>
int main() {
int a;
short b;
long c;
long long d;
printf("整形占用的内存为%u字节\n", sizeof(a));
printf("短整形占用的内存为%u字节\n", sizeof(b));
printf("长整形占用的内存为%u字节\n", sizeof(c));
printf("长长整形占用的内存为%u字节\n", sizeof(d));
return 0;
}
数据类型 | 占用空间 |
---|---|
short(短整型) | 2字节 |
int(整型) | 4字节 |
long(长整形) | Windows为4字节,Linux为4字节(32位),8字节(64位) |
long long(长长整形) | 8字节 |
PS:C/C++标准要求long占用的内存至少要和int一样大,而不是一定比int大。
虽然在 Windows 和Linux(32位)中int和long几乎没有区别,但它们仍是两种不同的类型。如果你有下面的函数声明:
void Foo(int value);
void Foo(long value);
那 Foo(1)
会调用前面那个函数,而 Foo(1L)
会调用后面那个函数。
字符型
字符型变量占用1个字节。char的本质就是一个1字节大小的整型。所以2个字符型变量可以做计算。
转义字符
转义字符 | 含义 |
---|---|
\b | 退格(BS) ,将当前位置移到前一列 |
\n | 换行(LF) ,将当前位置移到下一行开头 |
\r | 回车(CR) ,将当前位置移到本行开头 |
? | 代表一个问号 |
\0 | 数字0 |
\ddd | 8进制转义字符,d范围0~7 |
\xhh | 16进制转义字符,h范围0~9,a~f,A~F |
#include<stdio.h>
int main() {
printf("abc");//(1)
printf("\b456");//(2)
printf("\n");//(1)+(2)输出ab456
printf("abc");//(3)
printf("def");//(4)
printf("\r123\n");//(5) (3)+(4)+(5)输出123def,注意(5)中的\n不能少,否则输出123 ef
return 0;
}
数字在内存中的存储方式
原码
- 最高位做为符号位,0表示正,为1表示负
- 其它数值部分就是数值本身绝对值的二进制数
- 负数的原码是在其绝对值的基础上,最高位变为1
反码
- 对于正数,反码与原码相同
- 对于负数,符号位不变,其它部分取反(1变0,0变1)
补码
- 对于正数,原码、反码、补码相同
- 对于负数,其补码为它的反码加1
- 补码符号位不动,其他位求反,最后整个数加1,得到原码
在计算机系统中,数值一律用补码来存储。
两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃
有符号和无符号的取值范围
有符号的字符型取值范围:
−
2
7
-2^7
−27~
2
7
−
1
2^7-1
27−1
人为将“-0(1000 0000)”定义为区间最小负数,所以最小值不是-127,而是-128.
有符号的整形和长整型等同理。
有符号整形将“-0”定义成
−
2
31
-2^{31}
−231。
在Window或Linux(32位)下,有符号长整形将“-0”定义成
−
2
31
-2^{31}
−231。
无符号的字符型取值范围:0~
2
8
−
1
2^8-1
28−1(0000 0000 ~ 1111 1111)
无符号的整形和长整型等同理。
数据溢出
数据溢出后的值仍然在取值区间内,只不过走起了“循环”。
#include<stdio.h>
int main() {
char a = 127;//取值范围:-128到127
a = a + 1;
unsigned char b = 255;//取值范围:0到255
b = b + 1;
printf("a = %d, b = %d\n", a, b);//输出a = -128, b = 0
return 0;
}
字符串格式化输入与输出
字符串是内存中一段连续的char空间,以’\0’(数字0)结尾。
字符串常量与字符常量的不同:
每个字符串的结尾,编译器会自动的添加一个结束标志位’\0’,即 “a” 包含两个字符’a’和’\0’。
printf函数和putchar函数
- printf是输出一个字符串;
- putchar输出一个char;
printf格式字符:
打印格式 | 对应的数据类型 | 含义 |
---|---|---|
%p | void * | 以16进制的形式输出地址 |
%% | % | 输出一个% |
printf附加格式:
字符 | 含义 |
---|---|
l(字母l) | 附加在d,u,x,o前面,表示长整数 |
- | 左对齐 |
m(代表一个整数) | 数据最小宽度 |
0(数字0) | 将输出的前面补上0直到占满指定列宽为止不可以搭配使用- |
m.n(代表一个整数) | m指域宽,即对应的输出项(含小数点)在输出设备上所占的字符数。n指精度,用于说明输出的浮点数的小数位数。对数值型的来说,未指定n时,隐含的精度为n=6位。 |
#include<stdio.h>
int main() {
int abc = 10;
printf("abc = '%6d'\n", abc);// 输出abc = ' 10'
printf("abc = '%-6d'\n", abc);// 输出abc = '10 '
printf("abc = '%06d'\n", abc);// 输出abc = '000010'
printf("abc = '%-06d'\n", abc);// 输出abc = '10 '
double def = 12.3;
printf("def = '%6.2f'\n", def);// 输出def = ' 12.30'
printf("def = '%-6.2f'\n", def);// 输出def = '12.30 '
printf("def = '%06.2f'\n", def);// 输出def = '012.30'
printf("def = '%-06.2f'\n", def);// 输出def = '12.30 '
printf("def的内存地址:%p\n", &def);//输出def的内存地址:006FFBDC
printf("输出一个%%\n");// 输出一个%
return 0;
}
scanf函数与getchar函数
- scanf通过%转义的方式可以得到用户通过标准输入设备输入的数据;
- getchar是从标准输入设备读取一个char;
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
int a, b;
printf("请输入2个整数(以空格或回车作为分隔符):\n");
scanf("%d%d", &a, &b);
printf("您输入的2个整数是%d和%d\n\n", a, b);
printf("请输入2个整数(以逗号作为分隔符):\n");
/*
scanf的第一个参数可以指定输入的分隔符,
但是不能用\n作为分隔符,所以scanf("%d\n%d")是不允许的。
此处以逗号作为分隔符。
*/
scanf("%d,%d", &a, &b);
printf("您输入的2个整数是%d和%d\n\n", a, b);
printf("请输入2个整数(第一个整数最多为3位整数):\n");
scanf("%3d%d", &a, &b);
printf("您输入的2个整数是%d和%d\n\n", a, b);
return 0;
}
上述代码输入输出结果如下:
#include<stdio.h>
int main() {
char ch1, ch2;
printf("请输入第1个字符:\n");
ch1 = getchar();//此处输入一个字符后需回车才能输出下面的文字
printf("您输入的字符为%c\n", ch1);
/*
这里的getchar()是将上面的输入的回车读取出来,方便后面接收新的字符输入
*/
getchar();
printf("请输入第2个字符:\n");
ch2 = getchar();
printf("您输入的字符为%c\n", ch2);
return 0;
}