GCC编译器下32位机器和64位机器各个类型变量所占字节数:
C类型 32 64
char 1 1
short int 2 2
int 4 4
long int 4 8
long long int 8 8
char* 4 8
float 4 4
double 8 8
需要说明一下的是指针类型存储的是所指向变量的地址,所以32位机器只需要32bit,而64位机器需要64bit。
不同类型的数据之间进行的转换分为:
隐式转换:int - double = double (向数据类型占位多的类型转换)
显示转换 (强制类型转换)
特殊性:
1) char 类型不知道有没有符号
2)不同形式的0值:0,‘0’,“0”,‘0’
3)数据类型在后续代码中所使用的输入输出要匹配。
常量:在程序执行过程中值不会发生变化的量
分类:整形常量,实型常量,字符常量,字符串常量, 标识常量。
整形常量:1,23,678,7758
实型常量:3.14 ,6.28
字符常量:由n单引号引起来的单个字符或转义字符,如‘a’,‘b’,’\n’(换行),‘\r’(回车),‘\15’,’\x7f’
字符串常量:由双引号引起来的一个或者多个字符组成的序列(空串)
如:"",“a”,“avXXX”,“abc\n012\018”(代表abc \n 012 \0 18)
标识常量:#define 处理在程序的预处理阶段不占编译时间,一改全改(编译不做语法检查,只是单纯的宏名替换)
例如:#define PI 3.14ABC (编译不做语法检查)
#define ADD 2+3 (加()运算符优先级)
#define MAX(a,b) \
({typeof(a) A=a,B=b; ((A) > (B) ? (A) : (B);)}) //防止 MAX(a++, b++)
变量:用来保存一些特定的内容,并且在程序执行的过程中随时会发生变化的量
数据类型 标识符 值
TYPE NAME = VALUE;
标识符:由字母,数字,下划线组成不能以数字开头的一个标识序列。
存储类型:auto static register extern(说明型)
auto:默认,自动分配空间,自动回收空间。
resgister:寄存器(存储在cpu中运算速度快)类型,只能定义局部变量,不能定义全局变量,大小有限制,只能定义在32位的大小的数据类型,如double就不可以,寄存器没有地址,所以一个寄存器类型的变量无法打印地址查看或使用。
static :静态类型的变量,自动化初始化为0值或者空值,并且其变量的值有继承性。
extern:说明型,意味着不能改变被说明的变量或者类型。
变量的生命周期和范围
1)全局变量和局部变量
2)局部变量和局部变量
位运算的重要意义
将操作数中第n位置1,其他位不变:num = num | 1 << n;
将操作数中第n位置0,其他位不变:num = num & ~(1 << n);
测试第n位: if( num &1 <<n);
输入输出
格式化输入输出函数:scanf、printf
int printf(const char *format,...);
format: "%[修饰符]格式字符"
int scanf(const char *format,...);
format:预制符*
%s使用是比较危险的,因为不知道存储空间的大小。
scanf 放在循环结构中要注意能否接收到正常有效的内容。
printf ("[%s:%s]\n",FUNCTION,LINE);
linux下printf是以"行"来做缓冲区来刷新stdout的,如果遇到\n会强制立即刷新.否则刷新可能会延迟.因为printf中没有包含\n,内核决定满一行再刷新,而此时程序由于调用accept或recvfrom这类会block的api函数,造成屏幕一直显示不出来,除非收到了tcp连接请求或数据包,系统才会重新决定是否刷新屏幕.
看来小小的\n还是蛮重要的.
字符输入输出函数:getchar、putchar
字符串输入输出函数:gets、puts
gets:十分危险的函数,可以用fgets,getline来替代
scanf("%*6d%4d%2d%2d%*4d",&yy,&mm,&dd);
scanf里边也可以用通配符,比如下面代码中的scanf," %*6d " 。星号可以理解为赋值抑制字符,他表示从缓冲区中取6个字符,但是不赋值(也就是说不用写参数来接收他)。
流程控制
详解循环:while do-while for if-goto
while:(最少执行的次数为0)
while(exp)
loop;
do-while:
do
{
loop;
}while(exp);
数组
数组特点:在内存当中连续存放
一维数组
1 定义
【存储类型】 数据类型 标识符【下标】
2 初始化
不初始化
全部初始化
部分初始化
static
3 元素引用
数组名【下标】
4 数组名
数组名是表示地址的常量,也是数组的起始位置。
5 数组越界 (数组越界不做检查)
指针
1.变量与地址
变量名实际上是一个符号地址,在对程序编译连接时由系统给每一个变量名分配一个内存地址。在程序中从变量中取值,实际上是通过变量名找到相应的内存地址,从其存储单元中读取数据。
2.指针与指针变量
一个变量的(内存)地址称为该变量的“指针”,通过指针能找到以它为地址的内存单元。而指针变量是用来存放另一个变量的地址的(即指针)。
3.直接访问与间接访问
int i = 1;
int *p = &i;//一级指针
int **q = &p;//二级指针
printf("i = %d\n",i);//i的值1
printf("&i = %p\n",&i);//i的地址
printf("*p = %d\n",*p);//*p指针指向i的值1
printf("p = %p\n",p);//变量i的地址
printf("&p = %p\n",&p);//p指针的地址
printf("**q = %d\n",**q);//**q指针指向i的值1
printf("*q = %p\n",*q);//变量i的地址
printf("q = %p\n",q);//p指针的地址
printf("&q = %p\n",&q);/q指针的地址
/*
打印结果
i = 1
&i = 0x7fffe2cc2a2c
*p = 1
p = 0x7fffe2cc2a2c
&p = 0x7fffe2cc2a20
**q = 1
*q = 0x7fffe2cc2a2c
q = 0x7fffe2cc2a20
&q = 0x7fffe2cc2a18
*/
4.空指针与野指针
5.空类型
6.定义与初始化的书写规则
7.指针运算
8.指针与数组
指针与一维数组
指针与二维数组
指针与字符数组
- const与指针
- 10.指针数组与数组指针
数组指针:【存储类型】数据类型 (*指针名)【下标】= 值
如 :int (*p) [3] -> type name ->int [3] *p
12.函数与指针
指针函数
返回值 * 函数名人(形参);
如:int *fun(int);
函数指针
类型 (*指针名) (形参)
如:int (*p)(int);
函数指针数组
类型 (*数组名【下标】)(形参)
如:int (*arr【N】)(int);
指向指针函数的函数指针数组
如:int *(*arr【N】)(int);
11.多级指针
结构体
1 产生的意义
2 类型描述
stuct 结构体名
{
数据类型 成员1;//只是类型的描述
数据类型 成员2;
.........
};
;
3 嵌入定义
4 定义变量(变量,数组,指针),初始化及成员引用
成员引用:变量名.成员名
指针->成员名
(*指针).成员名
5 占用内存空间大小
结构体对齐&不对齐用于网络通信时使用
n的取值可以为1、2、4、8、16,在编译过程中按照n个字结对齐
#pragma pack(n)
取消对齐,按照编译器的优化对齐方式对齐
#pragma pack()
是说取消结构在编译过程中的优化对齐。
__attribute__ ((packed));
让所作用的成员对齐在n字节自然边界上,如果结构中有成员的长度大于n,则按照最大成员的长度来对齐
__attribute__ ((aligned (n)));
共用体
-
产生及意义
-
类型描述
union 共用体名
{
数据类型 成员名1;
数据类型 成员名2;
} -
嵌套定义
-
定义变量(变量,数组,指针),初始化及成员引用
成员引用:变量名.成员名
指针名->成员名 -
占用内存大小
-
函数传参(值,地址)
-
位域