C语言基础知识-数据类型

时间:2024-03-04 07:18:10

            C语言基础知识-数据类型

                                  作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

 

一.常量与变量

1>.关键字

    C的关键字共有32个。
1>.数据类型关键字(12个)     char,short,int,long,float,double,unsigned,signed,struct,union,enum,viod
2>.控制语句关键字(12个)
    if,else,switch,case,default,for,do,while,break,contiue,goto,return
3>.存储类型关键字(5个)
    auto,extern,register,static,const
4>.其他关键字(3个)
    sizeof,typedef,volatile

2>.数据类型

    数据类型的作用:编译器预算对象(变量)分配的内存空间大小。

1>.数据类型的定义
  变量的定义:
    数据类型 变量名[也叫标识符],如:"char Habby;"
  变量的赋值:
    变量名 = 值,如:“NAME=Jason Yin;”
    数据类型 变量名称[标识符] = 值,如:"int AGE = 10;"

2>.标识符的命名规则
  字母,数字,下划线组成;
  不能以数字开头(第一个字符必须为字母或下划线);
  见名知意;
  不能和同一函数内其他标识符重复;
  不能使用C语言内置的关键字;
  标识符中字母区分大小写;

 

3>.常量

常量的作用:
    在程序运行过程中,其值不能被改变的量;
    常量一般出现在表达式或赋值语句中;

举几个例子:
    整型常量    : 100,200,-100,0 等
    实型常量    : 3.149.18,1.44 等
    字符型常量 : \'a\',\'b\',\'10\',\'\n\'
    字符串常量 : "age","123","jason"

常量的定义:
  const 数据类型 常量名;
  #deifne 常量名 值 

注意:
  通过“#deifne”定义的常量是根据值来匹配数据类型的,推荐使用这种方式定义常量。
  const修饰的常量是不安全的,可以通过指针来修改

4>.变量

变量的作用:
    在程序运行过程中,其值可以改变;
    变量在使用前必须先定义,定义变量前必须有相应的数据类型;

变量特点:
  变量在编译时为其分配相应的内存空间;
  可以通过其名称和地址访问相应内存;  

5>.类型限定符

extenrn:
  声明一个变量,extern声明的变量没有建立存储空间。

const:
  定义一个常量,常量的值不能修改。例如 const int MONTH = 12volatile:
  防止编译器优化代码。

register:
  定义寄存器变量,提高效率。register是建议型的指令,而不是命令型的指令,如果CPU有空闲寄存器,那么register就生效,如果没有空闲寄存器,那么register无效。

6>.使用案例

[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat variable_definitions.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>
#define PI 3.1415926

int main(void)
{
    //定义变量
    int _age = 18;
    printf("Age={%d}\n",_age);

    //定义常量
    const int MONTH = 12;
    printf("一年有{%d}个月\n",MONTH);

    //引用使用"#define"定义的变量
    printf("圆周率为:{%f}\n",PI);
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o variable_definitions variable_definitions.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./variable_definitions 
Age={18}
一年有{12}个月
圆周率为:{3.141593}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 

 

二.进制

    进制也就是进制位,是人们规定的一种进位方法。对于任何一种进制-X进制,就表示某一位置的数运算时逢x进一位。十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,依次类推,x进制就是逢x进位。

1>.二进制

  二进制逢2进1,所有的数都是由0,1组成,如11+1=100
十进制转二进制:
    除二反序取余法(将十进制数每次除以2,取出余数,按照结果倒叙排序)。
二进制专十进制:
    权值法(将二进制各个位数从0位开始乘以2的N次幂,将各个位数的结果相加)。

  当前计算机系统使用的基本上都是二进制系统,数据在计算机中主要以补码的形式存储。以下一些术语大家可以了解一下:
    bit(比特)
      一个二进制代表以为,一个位只能表示0或1两种状态。数据传输是习惯以“位”(bit)为单位。
    Byte(字节)
      一个字节为8个二进制,称为8位,计算机中存储的最小单位是字节。数据存储是习惯以“字节”(Byte)为单位。
    WORD(双字节)
      2个字节,即16位。
    DWORD
      两个WORD,4个字节,即32位。
    1b
      1bit,1位。  
    1B
      1Byte,1字节,8位。
    1k,1K
      1024B。
    1M(1兆)
      1024k,1024*1024。
    1G
      1024M。
    1T
      1024G。
    1Kb(千位)
      1024bit,1024位。
    1Kb(千字节)
      1024Byte,1024字节。
    1Mb(兆位)
      1024Kb = 1024 * 1024bit。
    1MB(兆字节)
      1024KB=1024 * 1024Byte

2>.八进制

  八进制逢8进1,所有的数字是0到7组成。

  十进制转八进制:
    除八反序取余法(将十进制数每次除以8,取出余数,按照结果倒叙排序)。
  
  二进制转化为八进制:
    将二进制数字从右到左,每3个二进制数划分为一组,将每组数据的二进制转换成八进制对应的数字即可。
  八进制转换为二进制:     八四二一法则(将八进制的每一个位数上的数字拆开,分别用二进制表示即可。)

3>.十进制

  十进制逢10斤=1,有数字0-9组成,也是咱们生活中默认使用的进制。

  十进制转换成二进制,八进制,十六进制的方法我这里就不啰嗦了,过于简单我这里就不啰嗦了,我这里重点说一下十进制的小数转换成二进制的方式。
  
  十进制小数转换成二进制:
    小数部分和2相乘,取整数,不足1取0,每次相乘都是小数部分,顺序看取整后的数就是转化后的结果。为了方便说明,我们看一下十进制的0.521如何用二进制表示:
      0.521
    *    2
    ---------
      1.042   ---->第一次计算结果,取整数部分1,然后把小数部分0.042继续和2相乘
      
       0.042   ---->这里的0.042就是上面计算的1.042的小数部分
    *     2
    ----------
       0.084   ----->第二次计算结果,取整数部分0,然后把小数部分0.084机型和2相乘

       0.084   ----->这里的0.084是上面计算的0.084的小数部分
    *     2
    ----------
       0.168   ------>第三次计算结果,取整数部分0,并终止计算,因为十进制0.521只有3位小数,顾我们只需要取3位二进制位即可,最终结果为0.100
      
    如上所述,我们来总结一下十进制转换成二进制的几个要点:
      (1)乘的时候只乘小数部分;
      (2)0.521只有3位,因此我们只需要算出3位二进制位置即可;
      (3)0.521的二进制数为:0.100

4>.十六进制 

  十六进制逢16进1,由数字0-9和字母A-F组成。
  
  十进制转化为十六进制
    除十六反序取余法(将十进制数每次除以16,取出余数,按照结果倒叙排序,需要注意的是大于10的数字应该由A-F来表示)
  
  十六进制转化为十进制
    权值法(将二进制各个位数从0位开始乘以16的N次幂,将各个位数的结果相加)。

  十六进制转换为二进制
    八四二一法则(将十六进制的每一个位数上的数字拆开,分别用二进制表示即可。)

  二进制转换为十六进制  
    将二进制数字从右到左,每4个二进制数划分为一组,将每组数据的二进制转换成八进制对应的数字即可。

  十六进制转换为八进制  
    思路就是先将十六进制转换成二进制,再将二进制转换成八进制。
  
  八进制转换成十六进制
    思路就是先将八进制换转成二进制,再将二进制转换成十六进制。

5>.进制转换表

 

 6>.在C程序中进制打印案例

[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    //十进制数字10
    int a = 10;
    printf("%d\n",a);

    //定义八进制
    int b = 010;
    printf("%d\n",b);

    //定义十六进制
    int c = 0x10;
    printf("%d\n",c);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion 
10
8
16
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    //十进制数字10
    int a = 10;
    printf("%o\n",a);

    //定义八进制
    int b = 010;
    printf("%o\n",b);

    //定义十六进制
    int c = 0x10;
    printf("%o\n",c);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion 
12
10
20
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c    #以八进制方式显示
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    //十进制数字10
    int a = 10;
    printf("%x\n",a);

    //定义八进制
    int b = 010;
    printf("%x\n",b);

    //定义十六进制
    int c = 0x10;
    printf("%x\n",c);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion 
a
8
10
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c    #以十六进制方式显示
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    //十进制数字10
    int a = 10;
    printf("%X\n",a);

    //定义八进制
    int b = 010;
    printf("%X\n",b);

    //定义十六进制
    int c = 0x10;
    printf("%X\n",c);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o binary_conversion binary_conversion.c
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./binary_conversion 
A
8
10
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat binary_conversion.c    #以十六进制方式显示

 

三.sizeof关键字

  sizeof不是函数,所以不需要包含任何头文件,它的功能是计算一个数据类型的大小,单位为字节;
  
  sizeof的返回值为size_t;   sizeof_t类型在32位操作系统下是unsigned
int,是无符号的整数。
  
  注意:下面结果是根据64位操作系统获取的数据类型大小,此时案例可参考下面的“使用sizeof查看各个数据类型占用内存大小案例”
    char(字符型,1Byte) < short(短整型,2Byte) < int(整型,4Byte)|float(单精度浮点型,4Byte)|long(长整型,4Byte) < long long(长长整型,8Byte)|double(双精度浮点型,8Byte)
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat sizeof_demo.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    int a;
    int b=sizeof(a);    //sizeof得到指定值占用内存大小,单位为字节.
    printf("b=%d\n",b);

    size_t c = sizeof(a);    //用无符号的方式输出c的值
    printf("c=%u\n",c);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o sizeof_demo sizeof_demo.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./sizeof_demo 
b=4
c=4
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
sizeof使用案例
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat sizeof_demo2.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    int a = 10;
    //sizeof()求出数据类型在内存占用字节(Byte)大小
    int len1 = sizeof(a);
    printf("%d\n",a);
    printf("int = %d\n",len1);

    //单精度浮点型
    float b = 3.14;
    int len2 = sizeof(b);
    printf("%d\n",b);
    printf("float = %d\n",len2);
    
    //字符型
    char c = \'A\';
    int len3 = sizeof(c);
    printf("%d\n",c);
    printf("char = %d\n",len3);

    //双精度浮点型
    double d = 9.18;
    int len4 = sizeof(d);
    printf("%d\n",d);
    printf("double = %d\n",len4);

    //短整型
    short e = 10;
    int len5 = sizeof(e);
    printf("%d\n",e);
    printf("short = %d\n",len5);

    //长整型
    long f = 10;
    int len6 = sizeof(f);
    printf("%d\n",f);
    printf("long = %d\n",len6);

    //长长整型
    long long g = 10;
    int len7 = sizeof(g);
    printf("%d\n",g);
    printf("long long = %d\n",len7);
    
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o sizeof_demo2 sizeof_demo2.c
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./sizeof_demo2 
10
int = 4
2147483640
float = 4
65
char = 1
2147483639
double = 8
10
short = 2
10
long = 8
10
long long = 8
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
使用sizeof查看各个数据类型占用内存大小案例

 

四.计算机内存数值存储方式

1>.原码

一个数的原码(原始的二进制码)有如下特点:
    最高位作为符号位,0表示正,1表示负;
    其它数值部分都是数值本身绝对值的二进制数;
    负数的原码是在其绝对值的基础上,最高位变为1;

举个例子,我们用一个字节的原码来表示+15,-15,+0,-0
    +150000 1111
    -151000 1111
    +00000 0000
    -01000 0000

    原码表示方法简单易懂,带有符号数本身转换方便,只要符号位还原即可,但当两个整数相减或不同符号相加时,必须比较两个数哪个绝对值大,才能决定谁减谁,才能确定结果是正还是负,所以原码不便于加减运算。

2>.反码

一个数的反码(原始的二进制码)有如下特点:
   对于正数,反码与原码相同;
    对于负数,符号位不变,其它部位去反;
    
举个例子,我们用一个字节的反码来表示+15,-15,+0,-0
  +150000 1111
  -151111 0000
  +0 :  0000 0000
   -01111 1111

  反码运算也不方便,通常用来作为求补码的中间过渡

3>.补码

在计算机中,数值一律用补码来存储。补码特点如下:
  对于正数,原码,反码,补码相同;
  对于负数,其补码为它的反码加1;
  补码符号位不动,其他为求反,最后整个数加1,得到原码;
举个例子,我们用一个字节的补码来表示
+15,-15,+0,-0
  +15 : 0000 1111
  -15 : 1111 0001
  +0 : 0000 0000
  -0 : 0000 0000

如果对补码还迷糊的小伙伴,可参考博主推荐阅读:https://www.cnblogs.com/yinzhengjie/p/8666354.html
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat complement.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    int a = -15;
    printf("%x\n",a);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o complement complement.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./complement 
fffffff1
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 

/*
  如上所述,输出结果为“fffffff1”,改值用途二进制表示为:1111 1111 1111 1111 1111 1111 1111 0001

  符号位不变,其他去反,我们查看该二进制的反码为:1000 0000 0000 0000 0000 0000 0000 1110

  我们在反码的基础上加1,得到最终的补码为:1000 0000 0000 0000 0000 0000 0000 1111,即最高位是符号位,1代表负数,即改值二进制的补码表示的为-15.
*/
补码案例分析,使用C程序表示-15

4>.补码的意义

在计算机系统中,数值一律使用补码来存储,主要原因如下:
  统一了0的编码;
  将符号位和其他位统一处理;
  将减法运算转变为加法运算;
  两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。

 

五.整型(int)

1>.整型变量的定义和输出

%d
  输出一个有符号的10进制int类型

%o(字母o)
  输出8进制的int类型

%x
  输出16进制的int类型,字母以小写输出

%X
  输出16进制的int类型,字母以大写输出

%u
  输出一个10进制的无符号数
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome1.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    int a = 123;        //定义变量a,以10进制方式赋值为123.
    int b = 0567;        //定义变量b,以8进制方式赋值0567.
    int c = 0xabc;        //定义变量c,以16进制方式赋值为0xabc.
    
    printf("a = %d\n",a);
    printf("8进制:b=%o\n",b);
    printf("10进制:b=%d\n",b);
    printf("16进制:c=%x\n",c);
    printf("16进制:c=%X\n",c);
    printf("16进制:c=%d\n",c);

    unsigned int d = 0xffffffff;    //定义无符号int变量d,以16进制方式赋值
    printf("有符号方式打印:d = %d\n",d);
    printf("无符号方式打印:d = %u\n",d);
    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o int_dome1 int_dome1.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./int_dome1 
a = 123
8进制:b=567
10进制:b=375
16进制:c=abc
16进制:c=ABC
16进制:c=2748
有符号方式打印:d = -1
无符号方式打印:d = 4294967295
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome1.c      #使劲戳我可参考实际案例

2>.整型变量的输入

[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome2.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    int num;
    printf("请输入a的值:>>> ");

    //不要加换行符"\n"
    scanf("%d",&num);

    //打印输入的int类型的值
    printf("num = %d\n",num);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o int_dome2 int_dome2.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./int_dome2 
请输入a的值:>>> 20190520
num = 20190520
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 

3>.short,int,long,long long

short(短整型)
  2字节

int(整型)
  4字节

long(长整型)
  windows为4字节,Linux为4自己(32位),8字节(64位)

long long(长长整型)
  8字节

温馨提示:
  整型数据在内存中占用的字节数与所选择的操作系统有关。虽然C语言标准中没有明确规定整型数据的长度,但long类型整型的长度不能短于int类型,short类型整数的长度长于int类型。
  当一个小的数据类型赋值给一个大的数据类型,不会出错,因为编译器会自动转化。但是当一个大的类型赋值给一个小的数据类型,那么就可能丢失高位。

以下是整型常量及其所需类型
10
  代表int类型
10l,10L
  代表long类型
10ll,10LL
  代表long long类型
10u,10U
  代表unsigned int类型
10ul,10UL
  代表unsigned long类型
10ull,10ULL
  代表unsigned long long类型


接下来我们查看一下打印格式及其含义
%d
  输出int类型
%l  
  输出long类型
%ll
  输出long long类型
%hu
  输出unsigned short类型
%u
  输出unsigned int类型
%lu
  输出unsigned long类型
%llu
  输出unsigned long long类型
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome3.c
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    short a = 10;
    int b = 10;
    long c = 10L;
    long long d = 10LL;

    printf("sizeof(a) = %u\n",sizeof(a));
    printf("sizeof(b) = %u\n",sizeof(b));
    printf("sizeof(c) = %u\n",sizeof(c));
    printf("sizeof(d) = %u\n",sizeof(d));

    printf("short a = %hd\n",a);
    printf("int b = %d\n",b);
    printf("long c = %ld\n",c);
    printf("long long d = %lld\n",d);

    unsigned short a2 =20u;
    unsigned int b2 = 20u;
    unsigned long c2 = 20ul;
    unsigned long long d2 = 20ull;
    
    printf("unsigned short a = %hu\n",a2);
    printf("unsigned int b = %u\n",b2);
    printf("unsigned long c = %lu\n",c2);
    printf("unsigned long long d = %llu\n",d2);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o int_dome3 int_dome3.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./int_dome3
sizeof(a) = 2
sizeof(b) = 4
sizeof(c) = 8
sizeof(d) = 8
short a = 10
int b = 10
long c = 10
long long d = 10
unsigned short a = 20
unsigned int b = 20
unsigned long c = 20
unsigned long long d = 20
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat int_dome3.c        #使用案例

4>.有符号和无符号的区别

一个有符号的整型数据可以分为两部分:一部分是符号位,一部分是数字位。

无符号数据类型只包含数字位部分。

当我们写程序要处理一个不可能出现负数的时候,一般用无符号数,这样可以增大数的表达最大值。


有符号和无符号整型取值范围如下:
short   占用2字节,取值范围在-32768到32767(-2的15次方到2的15次方减1)。 int   占用4字节,取值范围在-2147483648代2147483647(-2的31次方到2的31次方减1) long   占用4字节,取值范围在-2147483648代2147483647(-2的31次方到2的31次方减1) unsigned short   占用2自己,取值范围在0到65535(0到2的15次方减1) unsigned int   占用4字节,取值范围在0到4294967295(0到2的32次方减1) unsigned long   占用4字节,取值范围在0到4294967295(0到2的32次方减1)

 

六.字符型(char)

1>.字符变量的定义和输出

    字符型变量用于存储一个单一字符,在C语言中用char表示,其中每个字符变量都会占用1个字节。在给字符型变量赋值时,需要用一对英文半角格式的单引号(\' \')把字符括起来。

    字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的ASCII编码放到变量中的存储单元中。char的本质就是一个1字节大小的整型。
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    char ch = \'a\';

    printf("sizeof(ch) = %u\n",sizeof(ch));
    
    printf("ch(%%c) = %c\n",ch);        //输出字符串
    
    putchar(ch);                //该方法只能输出字符,该行及下面一行均是输出字符
    
    putchar(\'\n\');
    
    printf("ch(%%d) = %d\n",ch);        //打印\'a\'对应的ASSCII的值

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o char_demo char_demo.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./char_demo
sizeof(ch) = 1
ch(%c) = a
a
ch(%d) = 97
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo.c

2>.字符变量的输入

[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo2.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    char input;
    
    //scanf("%c",&input);        //接收用户输入的一个字符
    
    input = getchar();        //除了使用上面的scanf方法获取用户输入,我们还可以用getchar来获取用户输入的字符

    putchar(input);            //将用户输入的字符打印出来
    
    putchar(\'\n\');            //上面打印出来并没有换行,我们可以人为的给它加一个换行符
    
    return 0;        
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o char_demo2 char_demo2.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./char_demo2
Y
Y
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo2.c

3>.ASCII对照表

ASCII码大致有以下两部组成:
  ASCII非打印控制字符:
    ASCII表上的数字0-31分配了控制字符,用于控制像打印机等一些外围设备。    

  ASCII打印字符
    数字32-126分配了能在键盘上找到的字符,当查看或打印文档时就会出现。数字127代表Del命令。
ASCII值控制字符ASCII值控制字符ASCII值控制字符ASCII值控制字符
0 NUT 32 (space) 64 @ 96
1 SOH 33 ! 65 A 97 a
2 STX 34 " 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 S 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 / 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 `
31 US 63 ? 95 _ 127 DEL
特殊字符解释
NUL空VT 垂直制表SYN 空转同步
STX 正文开始 CR 回车 CAN 作废
ETX 正文结束 SO 移位输出 EM 纸尽
EOY 传输结束 SI 移位输入 SUB 换置
ENQ 询问字符 DLE 空格 ESC 换码
ACK 承认 DC1 设备控制1 FS 文字分隔符
BEL 报警 DC2 设备控制2 GS 组分隔符
BS 退一格 DC3 设备控制3 RS 记录分隔符
HT 横向列表 DC4 设备控制4 US 单元分隔符
LF 换行 NAK 否定 DEL 删除

4>.转义字符

    所有的转义字符和所对应的意义:
转义字符
意义
ASCII码值(十进制)
\a
响铃(BEL)
007
\b
退格(BS) ,将当前位置移到前一列
008
\f
换页(FF),将当前位置移到下页开头
012
\n
换行(LF) ,将当前位置移到下一行开头
010
\r
回车(CR) ,将当前位置移到本行开头
013
\t
水平制表(HT) (跳到下一个TAB位置)
009
\v
垂直制表(VT)
011
\\
代表一个反斜线字符\'\'\\'
092
\\'
代表一个单引号(撇号)字符
039
\"
代表一个双引号字符
034
\? 代表一个问号 063
\0
空字符(NUL)
000
\ddd
1到3位八进制数所代表的任意字符
三位八进制
\xhh
1到2位十六进制所代表的任意字符
十六进制

 5>.数值溢出 

当超过了一个数据类型能够存放最大的范围时,数值会溢出。

有符号最高位溢出的区别:符号位溢出会导致数的正负发生改变,但最高位的溢出会导致最高位丢失。

char   占用1字节    取值范围在-128到127(负的2的7次方到2的7次方减1)

unsigned char    占用1字节    取值范围0到255(0到2的8次方-1
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat char_demo3.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    char input;
    
    //符号位溢出会导致数的正负发生改变,0x7f(十六进制表示法)对应的二进制为:0111 1111,给其加2后为:1000 0001,这是负数的原码,其补码为:1111 1111,十进制为-127.
    input = 0x7f + 2;    //127 + 2
    printf("%d\n",input);    

    //最高位的溢出会导致高位丢失,0xff(十六进制表示法)对应的二进制为:1111 1111,给其加1后变为:1 0000 0000,char只有8位最高位的溢出(有网友也喜欢说是高位截短),纠其原因是一个字节存取8个比特位,因此结果为:0000 0000,十进制为0.
    unsigned char input2;
    input2 = 0xff +1;     //255+1
    printf("%u\n",input2);

    //和上面案例原理相同,0xff(十六进制表示法)对应的二进制为:1111 1111,给其加2后变为:1 0000 0001,高位截断后结果为:0000 0001,十进制为1.
    input2 = 0xff + 2;
    printf("%u\n",input2);

    return 0;        
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o char_demo3 char_demo3.c 
char_demo3.c: In function ‘main’:
char_demo3.c:19:2: warning: large integer implicitly truncated to unsigned type [-Woverflow]        #我们在编译成可执行文件时,发现有warning的提示信息,说是无符号类型数据溢出(-Woverflow)啦,此消息咱们忽略即可,因为这个溢出是咱们人为造成溢出的~
  input2 = 0xff +1;  //255+1
  ^
char_demo3.c:23:2: warning: large integer implicitly truncated to unsigned type [-Woverflow]
  input2 = 0xff + 2;
  ^
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./char_demo3
-127
0
1
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 

 

七.实型(浮点型)

实型变量也可以成为浮点型变量,浮点型变量是用来存储小数数值的。在C语言中,浮点型变量分为两种:单精度浮点数(float),双精度浮点数(double),但是double型变量所表示的浮点数比float型变量更精确。

  float:占用4字节,7位有效数字。

  double:占用8字节,15~16位有效数字。

由于浮点型变量是由有限的存储单元组成的,因此只能提供有限的有效数字。在有效位以外的数字将被舍去,这样可能会产生一些误差。
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat float_demo.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main(void)
{
    float a = 3.14f;        //或者3.14F,这是传统赋值
    
    double b = 3.14;        

    printf("a = %f\n",a);
    printf("b = %f\n",b);

    a = 3.2e3f;                //或者3.2E3f,科学法赋值,表示3.2 * 1000 = 3200
    printf("a1 = %f\n",a);
    
    a = 100e-3f;                //表达式为:100 * 0.001 = 0.1
    printf("a2 = %f\n",a);
    
    a = 3.1415926f;
    printf("a3 = %f\n",a);        //结果为3.141593,因为我们知道a是float类型,占用4字节,仅仅有7位有效数字,最后一位会进行四舍五入法得结果

    float r = 2;

    float s = r * r * 3.14;

    printf("%.2f\n",s);          //注意,“%.2f"表示保留小数点后2位.

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o float_demo float_demo.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./float_demo 
a = 3.140000
b = 3.140000
a1 = 3200.000000
a2 = 0.100000
a3 = 3.141593
12.56
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 

 

.字符串格式化输入和输出

1>.字符串常量

字符串是内存中一段连续的char空间,以\'\0\'(数字0)结尾。
字符串常量是由双引号括起来的字符序列,如"chaina","C parogram","$PATH"等都是合法的字符串常量。

字符串常量与字符常量的不同:

每个字符串的结尾,编译器会自动的添加一个结束标志位“\0”,即"a"包含两个字符\'a\'\'\0\'

2>.printf函数和putchar函数

printf是输出一个字符串,putchar输出一个char。

printf格式字符:
打印格式      对应数据类型            含义
%d          int            接收整数值并将它表示为有符号的十进制整数
%hd         short int           端整数
%hu        unsigned short       无符号短整数
%o         unsigned int        无符号8进制整数
%u         unsigned int        无符号10进制整数
%x,%X       unsigned int        无符号16进制整数,x对应的是abcdef,X对应的是ABCDEF
%f          float           单精度浮点数
%lf         double           双精度浮点型
%e,%E        double           科学计数法表示的数,此处"e"的大小写代表输出时用"e"的大小写
%c          char            字符型,可以把输入的数字按照ASCII对应转换为对应的字符
%s          char *           字符串,输出字符串中的字符直至字符串的空字符(字符串以\'\0\'结尾,这个\'\0\'即空字符)
%p          void            以16进制形式输出指针
%%          %              输出一个百分号,即"%"


printf附加格式:
字符                含义
l(这个是小写字母l)        附加在d,u,x,o前面,表示长整数
-                 左对齐
m(代表一个整数)         数据最小宽度
0(这个是数字0)         将输出的前面补上0知道满指定列环位置不可用搭配使用-
m.n(代表一个整数)        m值域宽,即对应的输出项在输出设备上所占的字符数,n指进度,用户说明输出的实型数的小数位数。对数值型的来说,未指定n时,隐含的精度为n=6位。
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat echo.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    int a = 100;
    printf("a = %d\n",a);    //格式化输出一个字符串
    printf("%p\n",&a);    //输出变量a在内存中的地址编码
    printf("%%d\n");

    char c = \'a\';
    putchar(c);        //putchar只有一个参数,就是要输出的char
    
    long long a3 = 1000;
    printf("%lld,%llx,%llo\n",a3,a3,a3);

    int abc = 10;
    printf("abc = \'%6d\'\n",abc);
    printf("abc = \'%-6d\'\n",abc);
    printf("abc = \'%0d\'\n",abc);
    printf("abc = \'%-06d\'\n",abc);

    double d = 12.3;
    printf("d = \\'%-10.3lf\'\n",d);
    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o echo echo.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./echo 
a = 100
0x7fff18387bec
%d
a1000,3e8,1750
abc = \'    10\'
abc = \'10    \'
abc = \'10\'
abc = \'10    \'
d = \'12.300    \'
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat echo.c      #printf和putchar使用案例

3>.scanf函数与getchar函数

getchar是从标准输入设备读取一个char
scanf通过%转义的方式可以得到用户通过标准输入设备输入的数据
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat echo2.c 
/*
@author :yinzhengjie
blog:http://www.cnblogs.com/yinzhengjie
EMAIL:y1053419035@qq.com
*/

#include <stdio.h>

int main()
{
    char ch1;
    char ch2;
    char ch3;
    int a;
    int b;

    printf("请输入ch1的字符:>>> ");
    ch1 = getchar();
    printf("ch1 = %c\n",ch1);

    getchar();                //测试此处getchar()的作用
    
    printf("请输入ch2的字符:>>> ");
    ch2 = getchar();
    printf("\\'ch2 = %ctest\\'\n",ch2);

    getchar();                //测试此处getchar()的作用
    printf("请输入ch3的字符:>>> ");
    scanf("%c",&ch3);            //这里第二个参数一定是变量的地址,而不是变量名
    printf("ch3 = %c\n",ch3);    

    printf("请输入a的值:>>> ");
    scanf("%d",&a);
    printf("a = %d\n",a);

    printf("请输入b的值:>>> ");
    scanf("%d",&b);
    printf("b = %d\n",b);

    return 0;
}
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# gcc -o echo2 echo2.c 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# ./echo2 
请输入ch1的字符:>>> a
ch1 = a
请输入ch2的字符:>>> b
\'ch2 = btest\'
请输入ch3的字符:>>> c
ch3 = c
请输入a的值:>>> 100
a = 100
请输入b的值:>>> 200
b = 200
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# 
[root@node101.yinzhengjie.org.cn /yinzhengjie/code/day002]# cat echo2.c      #printf和getchar使用案例