概述
.1、在 C 语言中,sizeof() 是一个判断数据类型或者表达式长度的运算符。返回一个变量或者类型的大小(以字节为单位);例如:sizeof(int i);返回一个4,即为int类型的字节大小;
- char类型定义的变量大小为1个字节长度
short类型 为2个字节大小
int类型为4个字节大小
3、Typedef int INT32
Typedef struct tag_ts //结构体定义
{
INT32 B1;
INT32 B2;
}TS;
TS为两个INT32 即为8个字节
4、在计算机中,正负数表示:
最高位为1,表示为负数
最高位为0,表示为正数
例:
int sign = 0;
char i = -5;
short j = 5;
int k = 6;
sign = ( i & 0x80); //sign 结果不等于0,i表示二进制 10001001 最高位1表示为i的值为负数,与10000000“与”的结果为10000000 不为0;
Sign = ( j & 0x8000); // 根据i、j 、k不同的字节数据类型应选用不用字节大小。
Sign = (k & 0x80000000); //
- 计算机内部用补码表示有符号数:
正数的补码为正数本身;
负数的补码为负数的绝对值取反后加一;
例如:
5:0x00001001 ;-5:0x10001001 取绝对值得0x00001001 取反得0x11110110 再加一得0x11110111;
①、当无符号类型unsigned int i ,与有符号类型int j进行运算时,j经过取绝对值、取反后,会被看作一个很大很大的无符号类型;
即当有符号数与无符号数进行运算时,有符号数会被看作是无符号数进行运算;!!
例如:
unsigned int i=5;
int j=-5;
i+j>0;
而且j是一个非常非常大的一个值
5: 0x1000000000001001 取绝对值0x0000000000001001,取反得0x1111111111110110
0x1111111111110110为j的最终值!!
②、当定义一个unsigned int 类型i时,当i进行i--;操作时,i减到0后,如果再i--;i的值将会变为short类型两个字节的最大值了,即为0x11111110;
7、小数用二进制表示:
乘二取整:
例如:
0.25 化二进制 0.25x2=0.5 0.5x2=1 即为0.5d=0.1b (d表示十进制数,b表示二进制数);
再如:0.123 化二进制 0.123x2=0.246;0.246x2=0.492;0.492x2=0.984;0.984x2=1.968;
......................一直循环下去 最终得到的二进制为0.00011............b 在乘了四次2得到大于1的数,所以之前的位都是0;
- int类型的范围【-2的31次方~2的31次方】;
float类型的范围【-3.4x10的38次方~3.4x10的38次方】
Int和float都占4个字节内存,float比int范围大
原因:
float能表示的具体数字个数与int相同;
float可表示的数字之间不是连续的,存在间隙;
float只是一种近似表示法,不能作为精准数使用;
由于内存表示法相对复杂,(float二进制表示需要含符号位、指数、小数。Int只有符号位和指数。)float的运算速度比int慢
例如:
float f=3.1415f;
float f1=123456789;
printf(“%0.10fn”,f);//打印出来小数点后十位数据%0.10f即为打印小数点后十位数据;
printf(“%0.10fn”,f1);//打印出来小数点后十位数据%0.10f即为打印小数点后十位数据;
打印出来的
f=3.1414999962
f1=123546792.0000000000
打印出来的数据并不是实际的值,这就是为什么float不能做精准数使用;
- 强制类型转换:
目标类型能容纳目标值时,结果不变;
目标类型不能容纳目标值时,结果将发生截断。将高位截断,留下地位的数据;
自定义的结构体类型无法转化强制转化为基本类型;
- 变量属性:
auto关键字:它是C语言中局部变量的默认属性,即为所有变量都默认局部变量为auto属性 例如:
Void b(void )
{
Int i; //局部变量默认属性为auto
auto int j;//显示声明auto属性
}
register关键字:指明将局部变量储存于寄存器中,即为定义一个寄存器变量。且不能定义成全局变量,因为如果定义成全局变量,这个寄存器会在程序从开始运行到结束一直被占用,会导致CPU运行出现问题。且只能用于请求寄存器变量,但不一定成功。
不能用&运算符获得register的变量地址,因为&运算符获得的是内存地址,不是寄存器地址;
- static关键字:修饰局部变量,使用static定义局部变量时,将局部变量存储在程序静态区中,(一般定义局部变量是在栈上分配内存空间)
static定义全局变量时,所定义的全局变量只能在当前文件中被访问,不能在其他文件中使用;
例如1:
#include<stdio.h>
Int i ; //普通全局变量
static int j; //静态全局变量,只有当前文件夹能够访问
Int man()
{
Int k; //局部变量,在栈上分配空间
static int t; //静态局部变量,在静态数据区分配空间
}
例如2:
#include <stdio.h>
int f1()
{
int r = 0;
r++;
return r;
}
int f2()
{
static int r = 0;
r++;
return r;
}
int main()
{
for(i=0; i<5; i++)
{
printf("%dn", f1());
}
for(i=0; i<5; i++)
{
printf("%dn", f2());
}
return 0;
}
输出结果为:
F1():1、1、1、1、1
F2();1、2、3、4、5
原因:main()每次调用f1()时,r都被初始化为0,然后r++,为1
static定义的静态局部变量r,被存储在静态区中,main()在调用f2()时,只会对r进行一次的初始化为0的操作!;
- extern关键字:用于声明外部定义的变量或函数
也就是说,当看到一个被定义的变量前面有extern ,说明这个变量已经在其他地方定义好了。
Extern “C”
{
...........// 这种格式为C++的格式,是为了让编译器知道 这个大括号里是C语言的编程格式
}
12、if判断语句中。bool类型的可以写成if( bool)进行判断,因为bool类型的变量只有ture和fase两种值,如果if()中是判断是否为0,需要将0写在左边。例如:
if(0==i)
在判断语句中,float型数据不能直接与0值进行比较,需要定义一个接近于0值的数据,用于定位0的精度。例如:
#define a 0.000000001 //用于定位f的精度
float f = 0;
if((-a<=f)&&( f<=a)) // float型判断是否为0的判断语句
{
/
}
`{
/
}
13、break表示终止循环的执行
continue表示终止本次循环,进去下次循环执行
14、存在void类型的指针。
void*指针作为左值用于“接收”任意类型的指针
例如:int* t;
void* p;
p=t; //int*类型赋值给void*类型
t=p; //error 不能直接赋值给其他类型
void*指针作为右值使用时需要进行强制类型转换
15、const修饰的变量是只读的,本质还是变量。
修饰的变量只能出现赋值符号的左边,只能在右边。 它被存储在只读存储区。
当const定义一个值的时候,这个值存储在栈中。虽然是“常量”,其实可以通过改变在栈中分配空间地址里面的值进行修改的。例如:
void f(void)
{
const int c = 1; //const定义一个常量
//c = 5; //error 不能出现在赋值符号的左边。
int* p = (int*)&c; //通过指针将p指向c的地址
*p = 3; // 通过改变指针p的值,来改变p指向的地址的值!!
}
上面定义的为局部变量!!
定义为全局变量回出错。
const不能真正定义上的常量。
int const i;和const int i;一样,没有区别。
16、1.结构体与柔性数组
struct softarray
{
int len; //数组大小
int array[];//柔性数组,是一个大小未知的数组。
} //array仅是一个待定使用的标号符,不占用空间。
Struct softarray* sa = NULL; //定义一个sa的堆空间,NULL意思为空的意思,和’