目录
常见数据类型
char
int
short
long
long long
float
double
1.整型家族:
有符号的:最高位是符号位 0是整数 1是负数
无符号: 最高位是数值位
1.1 char
unsigned char
signed char
对于char 类型 默认为 signed和unsigned 是取决于编译器的
一般情况下都是 signed 很少被认为 unsigned
1.2 short
unsigned short[int] //int可省略
signed short [int]
1.3 int
unsigned int
signed int
1.4 long
unsigned long[int]
signed long[int]
1.5 long long
unsigned long long[int]
signed long long[int]
/short int long long long 都默认位 signed(有符号的)
关于short int long long long 的区别
可以看到在不同的系统下 不同类型所占字节数可能会不同
long long是标准的八字节
short 是标准的 二字节
浮点型家族
float
double
long double
构造类型(自定义类型)
>数组类型
>结构体类型 struct
>枚举类型 enum
>联合类型 union
关于数组类型
int arr[3]; //类型是 int [3]
int arr1[]={0,0,0};// 类型也是 int [3]
char arr2[4]; //类型是 char [4];
指针类型
int* pi;
char* pc;
float* pf;
double* pd;
void* pv;
空类型
通常用于函数的返回类型,函数的参数,指针类型等
void Add(void)//无返回值 无参数 { }
整型在计算机中以补码形式存在!
int main()
{
unsigned int ch=-10;
printf("%d\n",ch);//打印结果是-10
printf("%u\n",ch);//打印结果是4294967286
return 0;.
}
原因:
-10 的
原码:10000000000000000000000000001010
反码:11111111111111111111111111110101
补码:11111111111111111111111111110110
ch中存放的是-10的补码 也就是 1111111111111111111111111111110110
而%u是打印 无符号数 意思是你要我打印的一定是无符号数,不是无符号数我也认为是无符号数
所以1111111111111111111111111111110110 被认为是无符号数 因此 符号位被认为是数值为 打印出来的就是 4294967286
而 %d 打印的就是 有符号数 意思是你要我打印的一定是有符号数 不是有符号数我也认为是有符号数
所以1111111111111111111111111111110110 被认为是有符号数 所以符号位是就是符号位 结果是-10
练习2:
#include<stdio.h>
int main()
{
char a=-1;
signed char b=-1;
unsigned char c=-1;
printf("%d %d %d\n",a,b,c); //结果是 -1, -1, 255
return 0;
}
原因:
char a = -1;
-1 是整数
-1的
原码:10000000000000000000000000000001
补码:11111111111111111111111111111111
整形以补码形式存储在内存中
char类型只有八位 所以a的值是 11111111
而把 a以 %d 的形式打印出来 %d 是整形 所以需要发生整型提升!
打印的是有符号数 --->数据现在是补码 需要转换成原码
整形提升 前面补的是原来的变量的符号位
对于a 前面补1 -->1111111111111111111111111111111111
而打印出的是 数据的原码! 原码是 10000000000000000000000000000001 也就是 -1
对于 b 和a 是一样的
对于 c: unsigned char c=-1
c 同样也只能存放11111111
打印c的时候 c是无符号数 所以前面直接补0 ---> 00000000000000000000000011111111
打印数据的原码 正数的原码 就是他本身 所以打印出 255
关于变量的存储
首先要了解一下内存的三个区 如图所示
我们可以验证一下:
可以观察到:
全局变量c为0
局部变量a为随机值
那么 变量在内存中是怎么存储的呢?
我们知道 int 类型 10 的16进制为 00 00 00 0a
- -10 的16进制为 ff ff ff f6
为什么 在内存中是 倒着的呢? --- ------这就是大小端字节序的问题了
大小端字节序
对于多字节数据
0x 0 0 1 1 2 2 3 3
高字节 <----低字节
大端字节序存储:
把一个数据低位字节处的数据存放在高地址 处,把高位字节处的数据存放在低地址处
小端字节序存储:
把一个数据低位字节处的数据存放在低地址处,把高位字节处的数据存放在高地址处
而不同机器使用大端字节序还是小端字节序 不一定相同
上面的例子 就是使用了 小端字节序存储
为什么会存在大小端字节序问题呢?
因为在计算机系统中,是以字节为单位的 每个地址单元都对应着一个字节,一个字节为8bit
而C语言中 除了char类型是8bit short int long 等大于8bit的数据类型
另外对于 大于8位的处理器 如16位处理器和32位处理器,由于寄存器宽度大于一个字节,那
么必然存在着一个如何将多个字节安排的问题 所以产生了大小端存储模式!!
练习--设计一个函数来求出该机器是大端还是小端字节序
思路:
以 int a = 1 为例子我们只需要知道 第一个字节的内容就可以判断出来 是大端还是小端
但是 int类型的首地址我们怎么得到呢?
我们知道 &a得到的是a的起始地址 也就是首字节的地址
我们如果把&a 强制类型转换后 放到一个char* 类型里面 那么该地址后面的东西就没了
所以只剩下了首字节的地址 便可以实现了
如图 :
代码实现:
int main()
{
int a=1;
char* pa=(char*)&a;//必须要强制类型转换!!!!!
if(*pa==1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
判断大小端的函数代码
#include<stdio.h>
int sys()
{
int a = 1;
return *(char*)&a;//更简化了
}
int main()
{
int ret = is_sys();
if (ret == 1)
{
printf("小端\n");
}
else {
printf("大端\n");
}
return 0;
}