C编程基础day04

数据类型是为了告诉编译器 这个数据占用多大内存空间。

常量指在程序运行过程中其值不允许改变的量,常量一般出现在表达式或赋值语句中。
整型常量 2,-3、0;
实型常量 2.5, 3.14;
字符常量: ‘a’,'b';
字符串常量:“abcd”,“123456”;

变量指在程序运行过程中其值可以改变,变量使用前必须先定义,变量定义时必须说明数据类型。
变量名字 只能是字母、数字、下划线组成。 名字第一个字符必须是字母或下划线开头。
同一个{}内不允许出现两个名字相同的变量定义

变量的初始化 int b =10;
变量的赋值 b=200;

变量的声明 和 定义
变量声明不占用内存空间  extern int c;   /*只是声明没有空间就不能赋值*/
变量定义  int a=10;
int  a;  /*这种即使声明又是定义,此时的“声明”的时候创建空间*/
在main函数之前 extern int a=100; /*这是全部变量的声明占用内存空间*/

const int b =10; const 修饰变量为 只读。只读的变量 类似于常量。

数据在计算机当中是以 补码的形式存储的。
数据传输习惯以bit为单位。 1 bit
计算机存储最小单位是byte字节。1 Byte
1 Kb = 1024 bits
1 KB =1024 Bytes

10进制转化为2进制, 10进制的数除以2分别取商和余数,循环进行,当商为0的时候,余数倒着数转化的结果就是2进制。

小数的存储不准确,小数十进制存储, 小数部分乘以2,得到整数,循环进行,循环次数为小数位数。 顺着看三次乘以2的整数部分结果即为转换后结果。0.432 转换时候循环3次转换后为0.011
56.432存储时整数部分和小数部分分开存储
八进制和二进制转换:八进制的1位对应二进制的3位。
十六进制和二进制转换:十六进制进制的1位对应二进制的4位。
八进制和十六进制转换,先借助二进制转换为二进制再进行转换。

十进制正常表示,如 int a=123 。printf("十进制=%d\n",a);
八进制以0开头,如 int b=0123。 printf("八进制=%o\n",a);  /*o为小写字母o*/
十六进制以0x开头 如 int c=0x123  printf("十六进制=%x\n",a); /*x  X大小写都行,x对应小写的abc, X对应大写的ABC*/
二进制:C语言不能直接表示二进制。

原码、反码、补码
计算机以 补码的形式存储数字。

原码:站在用户的角度存原始的二进制。 
对于正负数最高位为0代表正数,最高位为1代表负数。
+1 : 0000 0001
-1 : 1000 0001
+0: 0000 0000
-0 :1000 0000
原码存储导致2个问题: 1、0有正0和负0两种存储形式。 2、正数和负数相加结果不正确 (计算机只会加不会减)
以原码来算1-1 = 1+(-1)
+1 : 0000 0001
-1 : 1000 0001
         1000 0010 = -2  所以使用原码不正确。

反码:正数的反码不变,负数的反码 相对原码符号位不变,其他取反 。  (反码、补码都是为了主要解决负数存储)
+1 : 0000 0001
-1 : 1111 1110
+0: 0000 0000
-0 : 1111 1111

反码存储导致1个问题:1、0有正0和负0两种存储形式。
以反码来算1-1 = 1+(-1)
+1 : 0000 0001
-1 : 1111 1110
         1111 1111 = -0   所以反码可以计算正数和负数计算。

补码:正数不变,负数的补码为负数的 反码+1. (正数的原码、反码、补码都一样。)( 反码、补码都是为了主要解决负数存储)
+1 :  0000 0001
-1 :   1111 1111
+0:    0000 0000
-0 :1   0000 0000  (因为只存储1个字节8bit,所以最高位丢弃,实际为0000 0000)
以补码来算1-1 = 1+(-1)
+1 :  0000 0001
-1 :  1111 1111
         0000 0000 =0  所以补码不仅可以解决正负数的计算,而且解决了0的正0和负0形式不一样问题。

负数的补码转换为原码 :符号位不变,其他位取反+1,即先取反码再加1. (切记 二进制的运算不要想当然的逆运算,即先减1再取反)

注意-128的补码均为1000 0000  ,, (稍后研究)

10进制数站在用户角度,原码
2进制、8进制、16进制站在计算机角度为 补码。
char    a =0x81;  /*因为不是10进制,所以为补码的形式*/
    printf("a=%d\n",a);  /*打印的为-127,因为展现给用户的%d为 原码形式打印,10进制用原码 */  /* 正数不会出现这种现象原因为正数的原码、反码、补码都一样 */
原因: 0x81 = 1000 0001 (0x81被当做补码形式)
                 =  1111 1110 (对补码求反码)
                 =  1111 1111   (最终求出0x81作为补码的原码= -127) 

      

int    a =-123;  /*因为是10进制,所以站在用户角度为原码形式*/
    printf("a=%x\n",a);  /*%x以4字节32位形式打印,因为是16进制所以 以补码的形式打印, 打印结果为0xffffff85 */   
-123 的原码 1000 0000 0000 0000 0000 0000 0111 1011
            反码 1111 1111 1111 1111 1111 1111 1000 0100
            补码 1111 1111 1111 1111 1111 1111 1000 0101
                     f            f      f      f         f        f        8        5
以上两种情况在是负数的时候尤其要注意。



有符号、无符号数的区别。
1、有符号最高位位1代表负数, 最高位为0代表正数。%d默认为有符号数。 singned int a;等价于int a; singned写不写无所谓
2、无符号为最高位是数的一部分,无符号数不可能是负数。 %u打印无符号数。unsigned int b ;代表b为无符号的正数。

%d以有符号形式打印
int a=0x8000007b;  /*由于不是10进制,所以a存的是补码*/
printf("a=%d\n",a); /由于是%d,所以原码呈现*/
0x8000007b作为补码 1000 0000 0000 0000 0000 0000 0111 1011
           补码的反码 1111 1111 1111 1111 1111 1111 1000 0100
          补码的原 码  1111 1111 1111 1111 1111 1111 1000 0101
                             -7          f      f      f         f        f        8        5  =-2147483525

printf("d= %d\n",0x8000007b); /*打印的为原码 -2147483525 */
%u直接以无符号数形式打印,%u无负数形式,最高位是数的一部分。
printf("u =%u\n",0x8000007b);/*打印的为2147483771*/
unsigned int c ;
c =0x8000007b; 
 printf("c_d=%d\n",c);/*打印的为-2147483525,因为虽然c为无符号数,但输出以%d为准,所以有符号形式输出*/
 printf("c_u=%u\n",c);/*打印的为2147483771,以无符号形式输出*/

字符型signed char的范围 -128~127
正数: 0 000 0000 ~ 0 111 1111 范围为0~127
负数: 1 000 0000 ~1 111 1111 范围为-0~-127
我们把-0当做-128来用
-128原码 1 1000 0000
-128反码 1 0111 1111
-128补码 1 1000 0000   /*-128的原码和补码一样的,char只占用8bit时候-128的补码和-0的原码,所以规定-128为1000 0000*/
字符型的unsigned char的范围都是正数 0000 0000 ~ 1111 1111 ,所以范围为0~255

赋值和运算时候千万不要越界
char c=127+2; /*c的最大值为127,此时会越界,129以二进制存储,所以是补码的形式*/
printf("c=%d",c);/*打印的结果为-127,打印为原码形式*/
129的二进制 1000 0001 /*129以二进制存储,所以是补码的形式,最高位为1说明这是负数的补码*/
       补码 1000 0001 /*这是负数的补码,其补码为*/
       反码  1111 1110
       原码  1111 1111  /*最高位是符号位,结果为-127*/

unsigned char c=255+2; /*c的最大值为257,此时会越界,257以二进制存储,所以是补码的形式*/
printf("c=%d",c);/*打印的结果为511*/
257的二进制 0001 0000 0001 /*257以二进制存储,所以是补码的形式,但是对于char类型我们只取后8bit*/
       补码 0000 0001 /*这是正数数的补码,正数的补码、反码、原码都一样*/

sizeof 是一个运算符, 类似+-*/,不是函数,是计算符

以下打印都是以4字节形式打印,虽然char是占1字节,但决定打印输出的是以下几种形式。
%d    输出有符号10进制int型
%u    输出无符号10进制int型
%o(小写字母o)  输出8进制int型
%x        输出16进制int型,字母小写
%X         输出16进制int型,字母大写

字符类型 char
1、内存中没有字符,只有数字。字符类型本质上是一个字节大小的整型。
2、一个数字对应一个字符,这就是ASCII码。
3、使用字符或数字给字符赋值是等价的。 char c; c='a‘;和c=97是等价的。’
4、小写字母比大写字母大32.
linux下使用man ascii 查看ASCII码

转义字符
\八进制转义字符
\x十六进制转义字符
\0和数字0等价

浮点型float 和 double主要是范围不一样。
浮点型能不用就不用,因为浮点型计算不准确。尤其是100.9等以9结尾的更容易出现。
flaot a=100.9;
printf("a=%f\n",a);/*打印结果为100.900002*/

类型限定符
extern  声明一个变量,extern声明的变量不建立存储空间。extern int a; extern还可以声明一个函数。
const 定义一个只读变量也就是常量,常量值不能被修改, const int  a= 100;
volatile  防止编译器优化代码,硬件的人用的比较多。 硬件做跑马灯时候有语句 a=1;a=2;a=3;a=4;分别指向4个灯分别亮,但是编译器可能会优化忽略前边3条指令,认为只有a=4;一条指令,从而造成跑马灯失效。
register 定义寄存器变量,提高效率。register是建议型指令而不是命令型指令。如果CPU有空闲寄存器register就生效,CPU没有空闲寄存器register就不生效



 

 






         








猜你喜欢

转载自blog.csdn.net/Shayne_Lee/article/details/80903972
今日推荐