C数据类型(64位机器为例)
整数类型
char 1 字节 -128 到 127 或 0 到 255
unsigned char 1 字节 0 到 255
signed char 1 字节 -128 到 127
int 4 字节 -2,147,483,648 到 2,147,483,647
unsigned int 4 字节 0 到 4,294,967,295
short 2 字节 -32,768 到 32,767
unsigned short 2 字节 0 到 65,535
long 4 字节 -2,147,483,648 到 2,147,483,647
unsigned long 4 字节 0 到 4,294,967,295
可以理解为,一个字节八位,2的八次幂就是256,0-255正好就是256个数字,若有符号,则为-128 到 127,若无则0 到 255,2字节、四字节的同理
sizeof 运算符。表达式 sizeof(type) 得到对象或类型的存储字节大小。
eg:
#include <stdio.h>
#include <limits.h>
int main()
{
printf("int 存储大小 : %lu \n", sizeof(int));
return 0;
}
输出:int 存储大小 : 4
浮点类型
float 4 字节 1.2E-38 到 3.4E+38 6 位有效位
double 8 字节 2.3E-308 到 1.7E+308 15 位有效位
long double 16 字节 3.4E-4932 到 1.1E+4932 19 位有效位
小数
单精度常量:2.3f 。
双精度常量:2.3,默认为双精度。
字符型常量
用英文单引号括起来,只保存一个字符'a'、'b' 、'*' ,还有转义字符 '\n' 、'\t'。
字符串常量
用英文的双引号引起来 可以保存多个字符:"abc"。
数据类型转换
隐式类型转换:隐式类型转换是在表达式中自动发生的,无需进行任何明确的指令或函数调用。它通常是将一种较小的类型自动转换为较大的类型,例如,将int类型转换为long类型或float类型转换为double类型。隐式类型转换也可能会导致数据精度丢失或数据截断。
显式类型转换:显式类型转换需要使用强制类型转换运算符(type casting operator),它可以将一个数据类型的值强制转换为另一种数据类型的值。强制类型转换可以使程序员在必要时对数据类型进行更精确的控制,但也可能会导致数据丢失或截断。
显示类型转换eg:
double d = 3.14159;
int i = (int)d; // 显式将double类型转换为int类型
C变量的变量定义
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为 C 是大小写敏感的。
C中变量的定义
格式:type variable_list;
type 表示变量的数据类型,可以是整型、浮点型、字符型、指针等,也可以是用户自定义的对象。
variable_list 可以由一个或多个变量的名称组成,多个变量之间用逗号,分隔,变量由字母、数字和下划线组成,且以字母或下划线开头。
C中变量的初始化
格式L:type variable_name = value;
type 表示变量的数据类型,variable_name 是变量的名称,value 是变量的初始值。
注意:变量不初始化的情况下,C 语言中变量的默认值取决于其类型和作用域。全局变量和静态变量的默认值为 0,字符型变量的默认值为 \0,指针变量的默认值为 NULL, 而局部变量没有默认值,其初始值是未定义的。
C 中的变量声明
变量的声明有两种情况:
1、一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。
2、另一种是不需要建立存储空间的,通过使用extern关键字声明变量名而不定义它。 例如:extern int a 其中变量 a 可以在别的文件中定义的。
除非有extern关键字,否则都是变量的定义。
eg:extern int i; //声明,不是定义
int i; //声明,也是定义
C 中的左值(Lvalues)和右值(Rvalues)
左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
整数常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
eg:
85 /* 十进制 */
0213 /* 八进制 */
0x4b /* 十六进制 */
30 /* 整数 */
30u /* 无符号整数 */
30l /* 长整数 */
30ul /* 无符号长整数 */
浮点常量
当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。
eg:
3.14159 /* 合法的 */
314159E-5L /* 合法的 */
510E /* 非法的:不完整的指数 */
210f /* 非法的:没有小数或指数 */
.e55 /* 非法的:缺少整数或分数 */
float myFloat = 3.14f;
double myDouble = 3.14159;
定义常量
使用 #define 预处理器: #define 可以在程序中定义一个常量,它在编译时会被替换为其对应的值。
使用 const 关键字: const 关键字用于声明一个只读变量,即该变量的值不能在程序运行时修改。
#define 预处理器定义常量的形式:
#define 常量名 常量值 eg:#define PI 3.14159
const 前缀声明指定类型的常量,如下所示:
const 数据类型 常量名 = 常量值; eg:const int MAX_VALUE = 100;在程序中使用该常量时,其值将始终为100,并且不能被修改。
请注意,把常量定义为大写字母形式,是一个很好的编程习惯。
#define 与 const 区别
1、替换机制:#define 是进行简单的文本替换,而 const 是声明一个具有类型的常量。
2、类型检查:#define 不进行类型检查,因为它只是进行简单的文本替换。而 const 定义的常量具有类型信息,编译器可以对其进行类型检查。
3、作用域:#define 定义的常量没有作用域限制,它在定义之后的整个代码中都有效。而 const 定义的常量具有块级作用域,只在其定义所在的作用域内有效。
4、编译器处理方式不同:#define 宏是在预处理阶段展开。const 常量是编译运行阶段使用。
5、#define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。(宏定义不分配内存,变量定义分配内存)、const常量会在内存中分配(可以是堆中也可以是栈中)。
6、const 可以节省空间,避免不必要的内存分配。
C储存类
auto 存储类
定义在函数中的变量默认为 auto 存储类,这意味着它们在函数开始时被创建,在函数结束时被销毁。
eg:
{
int mount;
auto int month;
}
register存储类
register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量 ,register 存储类定义存储在寄存器,所以变量的访问速度更快,在需要频繁访问的变量上使用 register 存储类可以提高程序的运行速度。
eg:
{
register int miles;
}
static存储类
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
静态变量在程序中只被初始化一次,即使函数被调用多次,该变量的值也不会重置。
eg:
#include <stdio.h>
/* 函数声明 */
void func1(void);
static int count=10; /* 全局变量 - static 是默认的 */
int main()
{
while (count--) {
func1();
}
return 0;
}
void func1(void)
{
/* 'thingy' 是 'func1' 的局部变量 - 只初始化一次
* 每次调用函数 'func1' 'thingy' 值不会被重置。
*/
static int thingy=5;
thingy++;
printf(" thingy 为 %d , count 为 %d\n", thingy, count);
}
运行结果为:
thingy 为 6 , count 为 9
thingy 为 7 , count 为 8
thingy 为 8 , count 为 7
thingy 为 9 , count 为 6
thingy 为 10 , count 为 5
thingy 为 11 , count 为 4
thingy 为 12 , count 为 3
thingy 为 13 , count 为 2
thingy 为 14 , count 为 1
thingy 为 15 , count 为 0
extern存储类
extern 存储类用于定义在其他文件中声明的全局变量或函数。当使用 extern 关键字时,不会为变量分配任何存储空间,而只是指示编译器该变量在其他文件中定义。当使用 extern 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
C预算符
算术运算符
+ 把两个操作数相加
- 从第一个操作数中减去第二个操作数
* 把两个操作数相乘
/ 分子除以分母
% 取模运算符,整除后的余数
++ 自增运算符,整数值增加 1
-- 自减运算符,整数值减少 1
a++和++a的区别
eg:
a=10;c=a++; 运行的结果是c=10,a=11,a++是将a先赋给前面的值,在将a+1;
a=10;c=++a; 运行的结果是c=11,a=11;++a是将a先进行加一,在将加一之后的a赋值给前面的数
关系运算符
==,!=,>,<,<=,>=
逻辑运算符
&& 称为逻辑与运算符。如果两个操作数都非零,则条件为真。
|| 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。
! 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。
位运算符
位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
p q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1
& 对两个操作数的每一位执行逻辑与操作,如果两个相应的位都为 1,则结果为 1,否则为 0。
| 对两个操作数的每一位执行逻辑或操作,如果两个相应的位都为 0,则结果为 0,否则为 1。
^ 对两个操作数的每一位执行逻辑异或操作,如果两个相应的位值相同,则结果为 0,否则为 1。
~ 对操作数的每一位执行逻辑取反操作,即将每一位的 0 变为 1,1 变为 0。
<< 将操作数的所有位向左移动指定的位数。左移 n 位相当于乘以 2 的 n 次方。二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)
>> 将操作数的所有位向右移动指定的位数。右移n位相当于除以 2 的 n 次方。二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补 0,负数左补 1,右边丢弃。
赋值运算符
=,+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|=
杂项运算符 ↦ sizeof & 三元
sizeof()
sizeof 是一个关键字、操作符,也是一个编译时运算符,其作用是返回一个对象或者类型所占的内存字节数。
(1)使用sizeof查看数据类型占空间大小
eg:sizeof(char)
(2)使用sizeof计算基本数据类型变量的占用空间的大小
eg:char c = 'a';sizeof(c)
(3)sizeof对变量名或者字面值可以不用括号,但是计算类型是必须要加括号的
(4)使用sizeof计算数组时,结果为数组长度*数组元素占用空间的大小
&
&可以返回变量的地址。&a; 将给出变量的实际地址。
三目运算符
表达式1?表达式2:表达式3;
先执行表达式1,如果表达式1的结果如果为真,那么执行表达式2,并且这个整体的运算式的结果是表达式2的结果;如果表达式1的结果如果为假,执行表达式3,运算式的结果是表达式3的结果。
eg: c=(a>b)?a:b;
等同于
if (a>b) c=a;
else c=b;