02-数据类型/常量/变量

1.数据类型

1.1 数据类型分类

  • 构造类型--用户自定义的数据类型
  • 存储负数使用有符号数
  • 字符型也分为有符号数和无符号数
#include <stdio.h>

int main()
{

}

1.2基本数据类型

bool类型

  • bool不是基本数据类型,使用的时候需要加入头文件
#include <stdbool.h>
#include <stdio.h>
#include <stdbool.h>  
int main()
{
  /*
    非0 为真
    0   为假
  */
  bool a;
  
  a = true;
  a = false;
 
  if(a) {
    print("true %d\n",a);
  }esle{
    print("false %d\n",a);
  }
  return 0;
}
#include <stdio.h>
#include <stdbool.h>  
int main()
{
  /*
    非0 为真
    0   为假
  */
  bool a;
  
  a = -1;  // a表示-1,非0为真
 
  if(a) {
    print("true %d\n",a);  // 结果为true 1
  }esle{
    print("false %d\n",a);
  }

  return 0;
}
  • 代码编译之前有一个预处理的过程,预处理过程会将一些宏进行展开
gcc -e ctype.c -o bool.i  
  • 编译的时候会将<stdbool.h>进行展开,编译文件中的bool被替换为_Bool说明进行了宏替换,这个宏是定义在<sdtbool.h>中的
// 原始的<stdbool.h>文件中,定义了宏,预处理的时候会进行宏替换,和头文件展开
#define bool _Bool
#define true 1
#define false 0

#define _Bool bool
#define bool bool

使用bool类型的两种方式

1.加头文件,使用bool(宏定义的布尔类型),如果想要使用true 1 false 0 要加头文件
2.不加头文件,使用_Bool,_Bool是基本数据类型

char类型

  • char 1个字节 -128-127或者0-255
  • signed char 1字节 -128-127
  • unsigned char 1字节 0-255
  • unsigned char 0000_0000 - 1111_1111 (0-255);255的计算可以看作是先加1,则最大值变为1_0000_0000(2^8 = 256),256-1 = 255
  • 有符号数的最大值,0111_1111(2^7-1 = 127)
  • -127 -- 原码 1111_1111,反码 1000_0000,补码 1000_0001
  • -128 -- 补码在内存中为1000_0000
#include <stdio.h>

int main()
{
  char ch;
  ch = 127;  // -128-127 是可以的
  ch = 65; // 可以打印A
  ch = 128; // 正数128赋值给ch,ch得到的补码是1000_000,char类型存储-128
  ch = 129; // 129的补码是1000_0001,char类型中127的补码也是1000_0001,所以存储127 
  
  unsigned char b;
  b = -1;  //b给的原码是1000_0001 反码 1111_1110 补码1111_1111  
           // b的补码对应unsigned char的存储值是255
  printf("ch=%d\n,%c\n",ch,ch);
  return 0;
}
  • 计算机是通过补码进行运算的,ch = 128,给到ch的原码是1000_0000,ch变量接收的是补码,相当于接收到1000_0000补码,补码1000_0000相当于-128;
  • b是无符号数,接收-1,-1给到补码1111_1111,b接收1111_1111之后当作正数的补码解析,255
  • 负数给的是补码,正数给的是原码;有符号类型接收的是补码,无符号接收的是原码
  • ch = 129,129将原码给到ch(1000_0001),ch将原码当作是补码进行解析,1000_0001还原为有符号整数,反码1111_1110,补码1111_1111,是127;

整型

  • short -- 2个字节和int -- 4字节--长度不同
  • sizeof(类型) -- 查看数据类型占几个字节
  • short -32768-32767
  • unsigned short 0-65535
#include<limits.h>  -- 这个头文件中有数据类型数据最大最小值的宏定义

2.常量

2.1 基本数据类型常量

常量是指在程序运行期间数值不发生变化的数据,整型常量通常简称为整数

整型常量

整数可以是十进制数\八进制数\十六进制数

// 3365
06434 -- 八进制数,0表示八进制
0xdlc -- 十六进制数,0x表示十六进制

浮点型数据

浮点型常量又称为实数,一般含有小数部分;在c语言中,实数只有十进制的实数,分为单精度和双精度;实数有两种表示方法,即一般形式和指数形式

3.24 
3.14 
-12.5

指数形式

  • 通常表示特别大的数或者特别小的数
  • e/E表示指数
1.176e+10
-3.5789e-8
// 0.0018
1.8e-3
#include <stdio.h>
int main()
{
  int a = 0x12345678;
  float b = 2.3e+10;
  printf("%d %x %o\n",a,a,a);
  printf("%e,%f\n",b,b);
  
  return 0;
}

字符型常量

字符常量指一个单一字符,其表示形式是由两个单引号包括的一个字符

'a'
'A'
'?'
'$'
'0'

在c语言中,字符常量具有数值,字符常量的值就是其对应的ASCII码制,可以将字符常量看作是一个字节的整数,这个值就是ascii码值

a = 'F'; // 将70给a   A -65  F是70
b = 'A'+2; // b中存储的是C字符
u = 'B'+' '; // 66+32 = 98 --b -- 大小写字母转换

  • 字符型变量赋值给的是ascii码值对应的字符
  • 字符型变量与整型进行运算,采用字符的ascii码值进行计算,得到ascii码值对应的字符
#include <stdio.h>

int main()
{
  char ch1,ch2,ch3;
  ch1 = 'A';    // A

  // ch2 = ch1 + 32;
  ch2 = ch1 + ' '; // a 空格的ASCII码是32
 
  ch3 = ch1 + 2 + ' '; // 'A'+2 = 'C'  -->c
  printf("%c %c %c\n",ch1,ch2,ch3)
  
  char ch4,ch5;
  ch4 = 0;
  ch5 = ch4 + 2;
  int a,b;
  printf("%c %c\n",ch4,ch5); // 字符0  字符2
  printf("%d %d\n",ch4,ch5); // ASCII码值 48  50
  // 字符0的ASCII是48,计算机看到字符0,实际存储的是48

  //将字符0和数字0进行转换,字符数字转换为数值数字-48  
  a = ch1 - 48;  // ch1 - 48就得到了数字0
  b = ch2 - 48; // ch2 - 48 --> 50-48=2 得到数字2
 
}

'0' + 2 // 得到的是字符2
字符常量与数字进行运算的时候,采用的是ascii码的数值进行运算

字符串常量

字符串常量:所谓字符串常量是指用双引号括起来的一串字符来表示的数据

"Hello World"
"Students"
"LINUX"
"李四"
"xxx"

'9'和"9"是一样的吗?

  • 使用数组存储一个字符串常量或者是使用一个指针存储一个字符串常量
  • 字符串是以\0为结尾的,"9"实际上是由'9'和'\0'组成的
#include <stdio.h>

int main()
{
  // 看起来是存储的是abc三个字符,实际上是四个,字符串以\0结尾
  // 数组arr[]里面不加长度,数组长度就是实际存储的数据的长度
  char arr[4] = {"abc"};
  char arr2[4] = {'a','b','c','\0'};
  
  // sizeof(数组名) -- 返回数组元素的总的长度共有多少个字节
  printf("%d,%d\n",sizeof(arr),sizeof(arr2)); // 4,4

  //%s 输出字符串
  printf("%s,%s\n",arr,arr2);
  return 0;
}

2.2 标识常量

  • 标识常量是指用标识符代替常量使用的一种常量,其名称通常是一个标识符
  • 标识常量也叫做符号常量,一般用大写英文字母表示,在使用之前必须先预定义
  • 方便进行程序的维护
// 表示符常量名称又叫做宏
#define <标识符常量名称> <常量>

#define MAX 50
#define PI 3.1415926
#define NULL 0
#define EOF -1
#define ERROR -1
#include <stdio.h>
#define ONE 1
#define TWO ONE+ONE    // 替换的时候用 1+1替换
#define TWO ((ONE)+(ONE)) // 用括号提升优先级


int main()
{
  int a = 10,b = 20;
  // 标识符变量指代的是后面的表达式的原样替换
  // 宏会被原样替代,不会进行运算出来
  c = ONE + TWO * b + a; // 1+1+1*20+10 = 32
  printf("%d\n",c);
  return 0;
}
#include <stdio.h>
#define W 3.0e-23
#define C 950

int main()
{
  float n,total;
  print("Please Input:")
  scanf("%f",&n);

  total = n * C / W;
  
  printf("%e\n",total);
  
  return 0;
}

3.变量

3.1 变量基础

变量在程序中用变量名表示,变量由用户根据其用途任意命名
变量名由数字\字母\下划线组成,不能以数字开头,不能和C的关键字重名
在程序运行时,变量占据内存空间的大小由其数据类型决定
变量在内存中的首地址,称为变量的地址

变量的说明

存储类型 数据类型 变量名
  • 存储类型有四种:auto\register\static\extern
  • 数据类型可以是基本数据类型,也可以是自定义的数据类型

存储类型

1.auto

  • auto说明变量只能在某个程序内使用,通常在函数体内或者函数中的复合语句中(局部变量,默认值是随机的)
  • 在函数体的某程序段内说明auto存储类型变量时,auto可以省略
auto int k;
int j;
double x;

2.register

  • register称之为寄存器类型,register变量是想将变量放入CPU寄存器中,这样可以加快程序的运行速度,如果申请不到就使用一般内存,同autos
  • 代码当中经常访问变量,小于等于四个字节的,存储到寄存器中
  • 寄存器变量,不能通过&获取register变量的地址
  • register变量必须是CPU所接受的类型,这通常意味着register变量必须是一个单一的值,并且长度小于或者等于整型的长度
  • 由于寄存器数量有限,真正起作用的register修饰符数目和类型都依赖与运行程序的机器
  • 在某些情况下,把变量存储在寄存器中反而会降低CPU运行速度,因为被占用的寄存器不能够在用于其他变量的存储或者变量被使用的次数不够多,造成额外的开销
#include <stdio.h>

int main()
{
  register int a = 10;
  printf("out if : a = %d\n %p\n",a,&a); // 报错
  return 0;
}

3.static

  • static变量称之为静态存储类型的变量,既可以在函数体内(局部变量),也可以在函数体外(全局变量)声明(默认是0)
#include <stdio.h>

int main()
{
  int a,i = 1;
  while(i<5) {
    int a;
    a++;
    printf("a = %d\n",a); // 打印的a的值都是随机值,a是局部变量,不给初值就是随机  
    i++;
  }
  return 0;
}


int main()
{
  int a,i = 1;
  while(i<5) {
    int a = 0;
    a++;
    printf("a = %d\n",a); // 打印的a的值都是1,局部变量在执行完一次之后会销毁
                          // 下次循环重新开辟空间存储
    i++;
  }
  return 0;
}


int main()
{
  int a,i = 1;
  while(i<5) {
    static int a;
    a++;
    printf("a = %d\n",a); // 打印的a是1 2 3 4 
                          // static修饰的a的初始值是0,循环一次不被销毁
    i++;
  }
  return 0;
}



int main()
{
  int a,i = 1;
  while(i<5) {
    static int a = 5;
    a++;
    printf("a = %d\n",a); // 打印的a是5 6 7 8 
                          // static修饰的a的初始值是0,循环一次不被销毁
    i++;
  }
  return 0;
}

局部变量使用static修饰具有如下特点:

  • 在内存中以固定地址存放,而不是以堆栈存放
  • 只要程序没有结束,就不会随着程序段的结束而消失,下次再次调用该函数,该变量不用再重新声明,而且还保留上次存储的值

4.extern

  • 当变量在一个文件中的函数体外声明(全局),所有其他文件中的函数或者程序段都可以使用这个变量
  • extern称为外部参照引用型,使用extern声明变量是想引用在其他文件中函数体外部说明的变量
  • static修饰全局变量,其他文件无法使用
// test1.c
#include <stdio.h>

int global_a = 10; // 可以被外部文件使用
static int b = 1000; // static修饰全局变量不能被外部文件使用
int main()
{
  return 0;
}
// test2.c
#include <stdio.h>

extern int global_a; // 告诉编译器我这个变量使用的是外部文件声明的变量
                     // 编译的时候需要两个文件同时进行编译

int main()
{
  printf("global a = %d\n",global_a); 
  return 0;
}

vi:VSP 文件 可以打开其他文件

posted @ 2023-05-14 14:52  Icer_Newer  阅读(28)  评论(0编辑  收藏  举报