C语言技术基础数据类型

整形

  •   概念:表达整数(非小数)类型的数据
  •   语法:

int a = 123;  //定义了一个专门用来存储整数的变量a 

                                                                            

  • 需要注意的地方: 

1. int 的本意是integer, 即整数的意思

2. int a 代表在内存中开辟一块小区域,称为a,用来存放整数,a一般被称为变量。

3.变量a所占内存大小,在不同的系统中是不一样的,64、32位系统典型的大小是4个字节

4.变量a有固定的大小,因此也有取值范围:-2147483648到2147483647

  • 整形修饰符:

short:用来缩短整形变量的尺寸,减少取值范围并节省内存,称为短整型(整形的一半 2个字节)

long: 用来增长整型变量的尺寸,增大取值范围并占用更多内存,称为长整形(long的大小是等于系统字长64位系统下long=8字节 32位系统long=4字节)

long long : 用来增长整形变量的尺寸,增大取值范围并占用更多的内存,称为长长整形(在64位或32位系统中都是8字节)

unsigned: 用来去除整形变量的符号位,使得整形变量只能表达非负整数

如何使用整形数据
#include <stdio.h>

int main(int argc , char const *argv[])
{

   int a = 123;      //123是一个十进制的整形数据 
   int b = 0x123F;  //0x123F 是一个十六进制的数据 其中0x表示十六进制
   int c = 0123;    // 0123是一个八进制的整形数据 其中0表示八进制
  

   /*
    %d  --> 对应的是十进制的整形

    %x  --> 对应的是十六进制的整形 , 小写 x 则输出十六进制的字母的时候会使用小写字母
      
    %X  --> 对应的是十六进制的整形 , 大写 X 则输出十六进制的字母
   
    %#x --> 对应的是十六进制的整形 , #则会把十六进制的前缀一并输出
  
    %o  --> 对应的是八进制的整形 
  
    %#o --> 对应的是八进制的整形   , #则会把八进制的前缀一并输出 
  
  */
         
    printf("a:%d b:%d c:$d\n" , a , b , c );  //把所有数据转化为%d 十进制的整形进行输出
    
    printf("a:%d b:%#x c:%#o\n" , a , b , c); // 通过使用 不同的格式控制符(%d %x %o..) 则可 
                                              //                      以使用不同的进制输出
   

}

  

short   int   a ; // 短整型

long    int   b ; // 长整型

long    long  int c ; //长长整形

unsigned int   e ; //  无符号整形

unsigned short  int f; // 无符号短整型

unsigned long int g;  // 无符号长整形

unsigned long long int  h //无符号长长整形 

  • 使用整形修饰符后 , 关键字 int 可以被省略:

short a ;  // 短整型

long b  ; //  长整型

long long c ; // 长长整形 

unsigned e; //无符号整形

unsigned short f; //无符号短整型

unsigned long g;   //无符号长整形

unsigned long long h ; // 无符号长长整形

sizeof运算符

sizeof看起来像是一个函数 ,但实际上他是一个运算符。

该变量类型或变量的大小 = sizeof(变量类型 、名字);

符号位 :

  •    对于有符号的整型数据,首位(最高位)为符号位,0表示正数,1表示负数。(100,-100)
  •    无符号的整形数据,没有符号位。

编码形式:

  •     原码:正数直接使用二进制来表达,比如short a=6 ,0000 0000 0000 0110;                              更改 a 的值a = -6;  此时 a 的原码就是 1000 0000 0000 0110

        通俗的理解,原码就是一个整数本来的二进制形式。

  •     反码:原码取反

  •     补码:原码取反+1,也就是反码+1(原码取反+1 == 补码+1)。符号位不变 如负数 -6的补码为  1111 1111 1111 1010 ,注意负数的补码在取反加一的时候,符号位是不动(保持是1)

        注意:以上都是针对负数的,正数的原码、反码、补码都是一样的           

  • 溢出    :超过数据所能表达的范围,称为溢出,就像汽车里程表,最大值和最小值是相邻的                   

                                                                        

  • 进制: 源码中(C语言代码)可以使用八进制、十进制或十六进制,但实际数据内存一律是二进制
  1. 十进制(默认),比如1099
  2. 八进制,比如013
  3. 十六进制,比如0x6FF0A
  • 格式控制符   
  1. int 整形:%d
  2. short 整形:%hd, h代表half,即一半的存储字节
  3. long 整形 :%ld
  4. long long整形:%lld
  5. 显示不同进制的前缀%#o、 %#x   

       

 浮点型(实型)

  • 概念:用来表达实数的数据类型
  • 分类:
  1. 单精度浮点型(float),典型尺寸是4字节
  2. 双精度浮点型(double),典型尺寸是8字节
  3. 长双精度浮点型(long double), 典型尺寸是16字节
  4. 占用内存越多,能表达的精度越高
  5. 浮点型是通过一定规则计算得到的二进制编码,因此计算的过程中一定可能会导致数据的不准确。

 float f1; // 单精度

double f2; //双精度

long double f3; //长双精度

 

字符 

char ch1 = 'a ' ;   //  'a'是字符常量,代表字母a

char ch2 = '\n' ;   //  '\n'是不可见字符常量,代表回车

 计算机存储的都是1和0(二进制),因此各种字符都必须被映射为某个数字才能存储到计算机中,因此字符型的数据实际是一个单字节的整形,这中映射关系形成的表为ASCll码表。

man ascii    //在linux下用这个命令可以查询ascii码表

 

#include <stdio.h>

int main(int argc , char const *argv[]) 

{

       char ch1  =  'a'  ;   //使用 ' a ' 表示一个字符常量  a --> 97 

       char ch2  =  98 ; 

       char ch3  =  '9'  ;  //这是一个字符9因此他所对应的ASCII 是57存储到内存 ch3中

       printf("%c\n" , ch1);   // %c 是一个格式控制符, 用于输出字符类型的数据

       printf("%o\n" , ch1);   // 以八进制的形式输出字符 a 的ASCII 的值

       printf("%d\n" , ch1);   // 以整形的形式输出字符 a 的 ASCII的值

       printf("%x\n" , ch1);   // 以十六进制的形式输出字符 a 的 ASCII的值

       

       printf("%c\n" , ch2);   // printf("%d\n" , ch1);   // 以整形的形式输出字符 a 的 ASCII的值

       printf("%d\n" , ch2);   // printf("%d\n" , ch1);   // 以整形的形式输出字符 a 的 ASCII的值

 

       printf("%c\n" , ch3);   // 输出得到字符 9 

       printf("%d\n" , ch3);   // 输出得到9所对应的ASCII值

      return 0; 

}

 字符本质上就是一个单字节的整形,支持整形所有的运算              

 char c1 = 20 ; 

 char c2 = c1 + 'a'  ;   //等价于char c2 = 20 + 97  ;

 

 printf("%c\n" , c2);   //以字符形式输出 117,即 'u’ 

 printf("%d\n" , c2);   //以整形形式输出117  

字符串 

  • 定义 

  //  字符串的定义方式有两种: 指针和数组

  char *s1  = "abcd" ;  //使用字符指针来表示字符串

  char s2[ ] = "abcd" ; //使用字符数组来表示字符串

   

  // 注意,使用数组来定义字符串时,方括号[ ]里面的数字可以省略 

  //  不省略也可以,但必须比字符串实际占用的内存字节数要大,比如:

  char s3[ ] = "apple" ;

 

  •  在内存中的存储
  1. 在内存中实际上是多个连续字符的组合
  2. 在任何字符串都以一个'\0'作为结束标记,例如:“funny story”的内存如下

  

 #include <stdio.h>

 

int main(int argc , char const *argv[ ] )  

{

       char * str1 = "Hello world" ;       //定义一个字符串指针【指向】“Hello world" 该数据不可                                                                       //以被修改 (因为数据被存放在常量区)

       char str2[ ] = "Hello world";       //定义一个数组,用于【存储】“Hello world” 该数据可修改(因为数据被存放在栈区) 

       printf("str1:%s\n" , str1)  ;

       printf("str2:%s\n" , str2)  ;   

       

       printf("str1:%p\n , str1);             //%p 是一个格式控制符,用于输出地址类型的数据

       printf("str2:%p\n , str2);             //%p 是一个格式控制符,用于输出地址类型的数据

                                                         

       return 0 ;

 }

通过地址我们不难看出,str1和str2存放的数据地址是不同的,因为str1的指针指向常量区(只读区域)数据,str2指向的是栈区

布尔数据类型

  • 概念:布尔型数据只有真、假两种值,非零为真,零为假。
  • 语法: 

 bool a = 1; //逻辑真。此处1可以取其他任何非零数值

 bool b = 0; //逻辑假

  • 注意
  1. 逻辑真除了1之外,其他任何非零数值都表示逻辑真,等价于1。
  2. true与false实际上就是两个值为1以及0的宏,因。
  3. bool类型以及布尔类型的变量都是1个字节
  4. 在使用bool类型的不管赋值是多少 bool b = -199; 实际上对变量b进行访问的时候他也只是1
  5. 使用布尔型bool定义变量时需要包含系统头文件stdbool.h
  6. 布尔型数据常用与逻辑判断、循环控制等场合。 

bool a = 0;

bool b = -199;     

bool c = true ;   //  true   -> 真 1  

bool d = false ;  //  false -> 假 0

 

printf("a:%d\n" , a) ;   // 0    

printf("b:%d\n" , b) ;   // 1 

printf("c:%d\n" , c) ;   // 1 

printf("d:%d\n" , d) ;   // 0

printf("true :%d\n" , true ) ;   // 1

printf("false:%d\n" , false) ;   //  0

printf("sizeof(bool):%ld\n" ,  sizeof(bool) ) ;   // 1  

printf("sizeof(a):%ld\n" , sizeof(a));   // 1

printf("sizeof(true):%ld\n" , sizeof(true));    // 4

printf("sizeof(false):%ld\n" , sizeof(false));   // 4 

ps:

      在C语言中,true是一个宏,其定义在stdbool.h头文件中,它代表的是布尔类型,然而,在C语言的标准中,并没有直接规定布尔类型的大小。这可能会因不同的实现而有所不同。在一些常见的C语言实现中(例如GCC和Clang),true被定义为整数类型,并且通常被实现为int类型的值,这使得sizeof(true) == sizeof(int)。 在这种情况下,sizeof(true)的值通常是4字节(32位系统)8字节(64位系统)。

常量与变量

  • 概念:不可改变的内存称为常量,可以改变的内存称为变量
  • 举例

  int  a =100;      //a是变量 , 而100是常量

  float  f =3.14    //f是变量  , 而3.14是常量

  char s[ ] = "abcd" ; //s是变量, “abcd”是常量      

  • 常量的类型

常量举例

说明

类型

100

整型

int

100L

长整型

long

100LL

长长整型

long long

100ULL

无符号长长整型

unsigned long long

3.14

双精度浮点型

double

3.14L

长双精度浮点型

long double

‘a’

字符型(单引号)

char

“abcd”

字符指针(字符串双引号)

char *

 

标准输入

  • 概念:键盘是系统的标准输入设备,从键盘中输入数据被称为标准输入
  • 相关函数:         

 scanf () ;   //格式化输入函数

 fegts () ;    //字符串输入函数

 int a ;

 float f;

 scanf("%d" , &a);    //从键盘输入一个整形,放入指定的内存地址&a中

 scanf("%f"  , &f );    //从键盘输入一个浮点数 ,放入指定内存地址&f中

 

 scanf("%d%f" , &a , &f);    //从键盘依次输入一个整形和一个浮点型数据,用空白符隔开

 

 char c;

 char s[10];

scanf("%c" , &c) ;    //从键盘输入一个字符,放入指定的内存地址&c中

scanf("%s" , s)   ;    //从键盘输入一个单词,放入指定的数组s中(注意不是&s)

 

fgets(s , 10 , stdin) ;  //从键盘输入一行字符串,放入数组s中

 #include <stdio.h>

 

int main(int argc , char const*argv[ ])

{

   //从标准输入(键盘)文件中读取指格式的数据,并把数据存入到指定的位置

   //%d是一个整形的格式控制符

   //&在当前语境中表示取地址

   int a = 999;

   float f ;

   printf("a:%d...\n" , a ) ;

   

   int ret_val = scanf("%d" , &a ) ;

   //scanf函数他默认回去扫描键盘文件并从中得到所要数据

   //而键盘(标准输入)文件他默认是阻塞的状态

   //阻塞 -> 当没有满足条件的数据情况下会导致进入挂起状态(暂停运行)

  

   printf("成功获得%d项数据....\n"  ,ret_val )

   printf("buf:%s\n" , buf) ;

  

   return 0 ;

}

注意:

  1. 在使用以上代码的时候如果第一次输入的数据并不符合scanf中要求的类型(比如要求输入%d整形,但是实际输入一个字符串“abc”),scanf则会直接返回失败,而且数据“abc”会直接被scanf留在缓冲区中,则有可能对后面的数据获取造成影响。
  2. 该函数的返回值是成功匹配到的项目数量,失败时返回0或-1 ,并会把不匹配的数据留在缓冲区。
  3. 可以配置getchar进行缓冲区的清理  while(getchar() != '\n' ) ; 
  4. 注意格式控制符的问题

  //在scanf中一定要慎重添加\n

  //注意参数中【格式控制符】: "%d,%c” 在输入数据的时候就需要严格匹配123 , h , 不     然会输入失败。

 int ret_val = scanf("%d" ,%c" ,&a ,&c) ; 

如何清空标准输入的缓冲区:

getchar()  // 默认从标准输入缓冲区获取一个字符

 

while(1)

{

      printf("%d\n" , getchar() );

 

 

fgets从指定文件中获取一行(\n)数据: 

函数原型 :

      char *fgets(char *s ,int size , FILE *stream);

参数分析:

     s --> 用于存储获得的数据的缓冲区入口地址

     size  -->  缓冲区的大小(用于控制获得的数量避免出现段错误【非法访问】)

     stream  --> 指定从该文件中获取数据

返回值:

    成功 返回第一个参数 s 

    失败 返回 NULL    

注意:

  • scanf 与 fgets的区别: 
  1. scanf 可以获取任意的基础数据类型, fgets则只能获取字符串类型
  2. scanf 的结束条件有 空格、TAB制表符 、回车
  3. fgets 的结束条件有 回车、 大小控制
  4. 如果都是获取字符串数据则建议使用fgets ,他可以控制获取的长度避免一些不必要的段错误

 

 类型转换

  • 概念:不一致但相互兼容数据类型,在同一表达式中将会发生类型转换。
  • 转换模式:
  1. 隐式转换:系统按照隐式规则自动进行转换
  2. 强制转换:用户显示自定义进行转换
  • 隐式规则:从小类型向大类型转换(低精度->高精度),目的是保证不丢失表达式中数据精度

 

隐式传唤示例代码

char a = 'a' ;

int b = 12 ;

float c =3.14;

float x =a +b -c;  //在该表达式中将发生隐式转换 , 所有操作数被提升float

   //数据类型的转换只会发生在运算表达式中,并不影响数据本身的类型(数据的类型从定义之初就已经确定无法被改变)

  • 强制转换:用户强行将某类数据转化为另一种类型,此过程可能丢失精度 

 char a = 'a' ;

 int b = 12 ;

 float c =3.14 ; 

 float x =a + b - (int)c ;   //在该表达式中a隐式自动转化为int , c被强制转化为int

不管是隐式转换,还是强制转化,变换的都是操作数在运算过程中的类型,是临时的,操作数本身的类型不会改变,也无法改变。

数据类型的本质

  • 概念:各种不同的数据类型,本质上是用户系统对某一块内存的数据(二进制)的解释方式的约定。
  • 推论:
  1. 类型转换,实际上是对先前定义的时候的约定,做了一个临时的打破
  2. 理论上,可以对任意的数据做任意的类型转化,但转化之后的数据解释不一定有意义
  3. 对于进程而言任何的数据都是一堆二进制编码,使用不同的规则来解析二进制编码都是可以的,只不过不一定有意义

12345678911  电话

12345678911  余额   //这个无意义

12345678911  寿命   //这个无意义

整形数据尺寸

  • 概念:整形数据尺寸是指某种整形数据所占用内存空间的大小
  • C语言标准并未规定整形数据的具体大小,之规定了相互之间的“相对大小”,比如:
  1. short 不可比 int 长   在(16位系统中short = int = 2字节  64位系统 int > short)
  2. long 不可比 int 短 (32系统long = int  64系统long > int)
  3. long型数据长度等于系统字长
  • 系统字长: CPU一次处理的数据长度,称为字长。比如32位系统、64位系统。
  • 典型尺寸
  1. char 占用1个字节
  2. short 占用2个字节
  3. long long在32位系统中一般占用8个字节,在64位系统中一般占用8个字节
  • 存在问题
  1. 同样的代码,放在不同的系统中,可能会由于数据尺寸发生变化而无法正常运行。
  2. 因此,系统标准整形数据类型,是不可移植的,这个问题在底层代码中尤为突出

 u_32t

 u_16t

 s_64t

可移植性整形

  • 概念: 不管放到什么系统,尺寸保持不变的整形数据,称为可移植性整型
  • 关键: typedef给变量类型取别名 

typedef  int  int32_t  ; // 将类型int 取个别名 ,称位int32_t

typedef  int  int32_t  ; // 将类型int 取个别名 ,称位int64_t 

  • 思路
  1. 为所有系统提供一组固定的、能反应数据尺寸的、统一的可移植性整型名称
  2. 在不同的系统中,为这些可移植性整型提供对应的typedef语句
  • 系统预定义的可移植性整形:

 

          

下表列举了C语言中常用的格式控制符,以及它们对应的数据类型和描述:

格式控制符

数据类型

描述

%d

int

十进制有符号整数

%u

unsigned int

十进制无符号整数

%o

unsigned int

八进制无符号整数

%x

unsigned int

十六进制无符号整数,使用小写字母

%X

unsigned int

十六进制无符号整数,使用大写字母

%f

float

浮点数

%lf

double

双精度浮点数

%c

char

单个字符

%s

char*

字符串

%p

void*

指针地址

%n

int*

存放已经输出字符数的变量指针

%%

N/A

输出 % 符号

 

其中,有些格式控制符还可以附加一些修饰符,例如:

修饰符

描述

-

左对齐输出

+

强制输出带有符号数的正负号

空格

输出值为正时冠以空格,值为负时印以负号

#

使用其他进制输出值时,增加前缀 0x 或 0

0

数字前面填充 0 而非空格

.精度

指定浮点数精度,或字符串输出的最大字符数

例如,可以使用格式控制符 "%.2f" 输出一个保留两位小数的浮点数。此外,还可以使用 "%3d" 控制输出的整数位数为 3。

好啦!相信你已经能拿捏数据类型啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值