数据的存储

C语言的类型

1.内置类型

char

short

int long float

double

2.自定义类型(构造类型)

类型的意义: 

1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。

2. 如何看待内存空间的视角。 

int main()

{

int a=10;//4         0a 00 00 00

float f=10.0;//4    00 00 20 41

return 0;

}

整形家族

char//char在内存中存储的是acs码值,属于整形,C语言标准并没有确定有误符号,取决于编译器,大部分默认是signed char 
    unsigned char//有符号的char指的是在char所表示的一个字节(8个二进制位)中,无符号表示(11111111表示255),可以表示0~255
   signed char//有符号的char指的是在char所表示的一个字节(8个二进制位)中,最高位表示符号位,1表示负数,0表示正数(11111111表示127),可以表示-128~127
short

    unsigned short [int]//int可以省略也可以写上

    signed short [int]
int
   unsigned int 

    signed int
long
   unsigned long [int]//int可以省略也可以写上
    signed long [int]

浮点型家族

float

double

long double

构造类型(自定义类型)

> 数组类型

> 结构体类型 struct 

> 枚举类型 enum

> 联合类型 union 

指针类型

大小恒定,都是四个或八个字节

int *pi;
char *pc;
float* pf;
void* pv;//无具体类型的指针

空类型

void 表示空类型(无类型) ,没有返回值

通常应用于函数的返回类型、函数的参数、指针类型。

void test()//如果括号中没有写任何内容,可以传参,也可以不传参,如果想要规定函数明确不需要传递参数,可以在括号中加上void

{

printf("呵呵\n");

}

int main()

{

test(100);

return 0;

}

整形在内存中的存储

int main()

{

int a=20;//14 00 00 00

//00000000 00000000 00000000 00010100原码

//00000000 00000000 00000000 00010100反码

//00000000 00000000 00000000 00010100补码

//0X 00 00 00 14转换为十六进制位

int b=-10;//f6 ff ff ff

//10000000 00000000 00000000 00001010原码

//11111111 11111111 11111111 11110101反码

//11111111 11111111 11111111 11110110补码

//0X ff ff ff f6转换为十六进制位

return 0;

}

计算机中的整形有三种表示方法,即原码、反码和补码。

 三种表示方法均有符号位(最高位)和数值位两部分,符号位都是用0表示“正”,用1表示“负”,

而数值位 负整数的三种表示方法各不相同。 

原码 

 直接将数字按照正负数的形式翻译成二进制就可以。

反码 

 将原码的符号位不变,其他位依次按位取反就可以得到了。

补码 

反码+1就得到补码。 

//无符号数的原码,反码,补码是相同的。

//正整数的原码,反码,补码,相同

//内存中存储一个整数存储的是它的二进制序列的补码

对于整形来说:数据存放内存中其实存放的是补码。 为什么呢? 

在计算机系统中,数值一律用补码来表示和存储。

原因在于,使用补码,可以将符号位和数值域统 一处理;

同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,

其运算过程 是相同的,不需要额外的硬件电路。 

int main()

{

//1+(-1)

//00000000 00000000 00000000 00000001 一的原码

//10000000 00000000 00000000 00000001 负一的原码

//原码相加为-2

//10000000 00000000 00000000 00000001负一的原码

//11111111 11111111 11111111 11111110负一的反码

//11111111 11111111 11111111 11111111负一的补码

//00000000 00000000 00000000 00000001 一的补码

//将两个补码相加,进位到第三十三个比特位上,所以输出结果为0,计算正确

return 0;

}

整数

1.有符号数

正数:原码,反码,补码相同

负数:原码,反码,补码不相同

2.无符号数

原码,反码,补码相同

int main()

{

int a=20;

//00000000 00000000 00000000 00010100

//0X 00 00 00 14

return 0;

}

这里设置的类型的用途在使用的时候定义该数据的类型,但具体怎么用,还要看是以什么样的形式打印出来。

unsigned int ch=-10;

%u打印的是无符号数,意思是你要我打印的一定是无符号数,不是无符号数,我也认为是无符号数。

%d打印的是有符号数,意思是你要我打印的一定是有符号数,不是有符号数,我也认为是有符号数。

大小端

什么大端小端: 

 大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;(倒着存)

小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地 址中。(正着存)

0X    11(高位) 22 33 44(低位) //左边是高位,右边是低位

编号小-低地址

编号大-高地址

大端字节序存储模式

小段字节序存储模式

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元 都对应着一个字节,一个字节为8 

bit。但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编 译器),另外,对于位数大于8位 

的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如 何将多个字节安排的问题。因此就 

导致了大端存储模式和小端存储模式。

例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为 

高字节, 0x22 为低字节。对于大端

模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式, 

刚好相反。我们常用的 X86 结构是

小端模式,而 KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以 

 由硬件来选择是大端模式还是小端
 模式。

百度2015年系统工程师笔试题:

 请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分) 

int main()

{

//把第一个字节的内容取出

int a=1;

char*p=(char*)&a;//强制转化类型

if(*p==1)

{

printf("小端存储");

}

else

{

printf("大端存储");

}

return 0;

}

封装成一个函数check_system

check_sys()

{

int a=1;

return *(char*)&a;

}

//指针类型的定义

//指针类型决定了指针进行解引用操作能访问几个字节,char*类型的指针只能访问一个字节,int*类型党的指针能够访问四个字节

//指针类型决定了指针+1,-1操作时,加的/减的是几个字节

int main()

{

//返回1,小端

//返回0,大端

int ret=check_sys;

if(ret==1)

{

printf("小端");

}

else

{

printf("大端");

}

check_sys();

return 0;

}

练习

1.

//输出什么? 

#include  int main()

{

    char a= -1;

    //10000000 00000000 00000000 00000001原码

   //11111111111111111111111111110反码

   //11111111111111111111111111111补码

   //11111111

    signed char b=-1;

   //11111111

    unsigned char c=-1;

   //11111111

    printf("a=%d,b=%d,c=%d",a,b,c);

   //发生整形提升,有符号数高位补位和符号位一致

   //无符号数高位补0

    return 0;

}

输出结果为-1,-1,255

2.

#include

int main() 

{

    char a = -128;

//10000000 00000000 00000000 10000000原码

//11111111 11111111 11111111 01111111反码

//11111111 11111111 11111111 10000000补码

//10000000

//11111111 11111111 11111111 10000000整形提升

    printf("%u\n",a);//%u为无符号的十进制数,无符号数的补码和原码相同
    return 0;

}

3.

#include

int main() { 

    char a = 128;
    printf("%u\n",a);
    return 0;

}

输出结果为4294967168

4.

int i= -20;

unsigned int j = 10;

printf("%d\n", i+j); 

//按照补码的形式进行运算,最后格式化成为有符号整数

10000000 00000000 00000000 00010100//-20的原码

11111111 11111111 11111111 11101011//反码

11111111 11111111 11111111 11101100//补码

00000000 00000000 00000000 00001010//10的原码

11111111 11111111 11111111 11110110//10和20的补码相加结果为补码

11111111 11111111 11111111 11110101//反码

10000000 00000000 00000000 00001010//原码结果是-10

5.

#include//睡眠函数

unsigned int i;
for(i = 9; i >= 0; i--)
{
     printf("%u\n",i);

       sleep(100);

}

因为i是一个无符号数,所以i永远也不可能变成负值,所以这个循环会变成死循环

char

signed char

unsigned char

1个字节

8个bit位

有符号char的范围-128-127

无符号char的范围0-255

6.

int main() 

{

    char a[1000];//数组下表0~999
    int i;
    for(i=0; i<1000; i++)
    {
         a[i] = -1-i; 

   } 

    printf("%d",strlen(a));
   return 0;

 } 

数组中存储的数分别是-1,-2,-3,-4,-5,-6……

但一个char类型的变量只能够表示-128~127范围的数字

每一个数据被存储之后就会变成-128~127之间的数字

从右边的循环图可知道

从-1~-128之后变成127~1,1之后是0,遇到\0,strlen的读取就停止了

所以一共为255个数字

7.

#include

unsigned char i = 0;
int main()
{

        for(i = 0;i<=255;i++)
        {

                printf("hello world\n");
        }

       return 0;

 } 

该代码为死循环

unsigned char的取值范围是0~255

255+1=0

所以这个循环条件会一直成立,从而陷入死循环。

你可能感兴趣的:(linq,p2p,c++,windows)