C 语言学习笔记(2)

内容提要

  • 变量
  • 基本类型数据

回顾

  • 基本类型
    • 整型
      • 短整型:short(2字节)
      • 基本型:int(4字节)
      • 长整型:long(32位系统4字节/64位系统字节)
      • 长长整型:long long(8字节,C99新增)
    • 浮点型
      • 单精度型:float(4字节)
      • 双精度型:double(8字节)
      • 长双精度型:long double(如GCC通常是16字节,MSVC)编译器决定
    • 字符型:char(1字节)
  • 构造类型
    • 构造体:struct
    • 共用体/联合体:union
    • 枚举:enum
  • 指针类型
  • 空类型:void

常量

定义:程序运行过程中值不变的量。

存储位置:

  • 常量可能存储在数据段(如字符串常量)或代码段,具体由编译器决定。
  • 变量默认存档在栈内存,但静态变量和全局变量存储在数据段。

常量的分类:

  • 整型常量
  • 浮点型常量
  • 字符型常量
  • 字符串型常量
  • 符号常量
    • 定义符号常量(宏定义):#define PI 3.14

变量

概念

在程序运行过程中值可变的量,称为变量

  • 变量代表内存中(栈内存)具有特定属性的一个存储单元,它是用来存储数据的,也就是存放变量的值。
  • 变量应该有一个名字,以便于通过名字访问变量。

在这里插入图片描述

格式

数据类型 变量名列表;

范例

include <stdio.h>
int main(int argc,char *argv[])
{
    // 1. 声明变量并初始化(解释:从内存中申请一块存储空间,并给这个空间添加一个初始的数据)
    // 变量名,就是标识符的一种,命名规则:以下划线或者字母开头,后面只能跟数字、字母、下划线,建议使用小写字母+下划线,举例:set_user
    int age = 21;  // 注意:=在程序中不是关系运算符,这里称作赋值运算符,意思就是将=右边的值赋值给左边变量对应的变量空间(从右往左)
   
    // 2. 先声明,再赋值
    int count;
    count = 10;
    
    // 3. 初始化和赋值并行
    int number = 12;
    printf("%d\n",number);// 12 %d:以10进制整型的方式格式化输出
    number = 22;
    printf("%d\n",number);// 22 我们对同一个变量赋值,后赋值的数据会覆盖掉先赋值的数据
    
    // 4. 我们可以为多个变量定义同一类型,多个变量之间使用逗号分隔。
    int a,b=10,c;//此时我们定义了3个变量,只有变量b初始化了,其他两个变量处于未初始化状态
    //访问未初始化的变量
    //访问一个未初始化的变量不会报错,但是不建议访问,因为此时变量空间中的数据是操作系统分配的随机值
    printf("%d,‰d,%d\n",a,b, c);
    
    return 0;
}

基本类型:(整型、浮点型、字符型)我们创建变量的同时,在内存中开辟对应的内存空间

命名规则

  • 以字母或下划线开头,后面跟字母、数字、下划线。举例:_int,number,num1

  • 不能与关键字(如:if…int…)或预定义标识符(如:printf…main…)重名。

  • 变量名、变量值、变量所占存储单元之间的关系:

    在这里插入图片描述

标识符

定义:用来表示对象名字的有效字符。对象包括变量、常量、函数、数组、结构类型等。也就是标识符就是对象的名字。

构成

  • C语言规定的标识符只能由字母、数字、下划线3中字符构成。且只能以下划线或者字母开头。如:_int,number

  • 编译系统对字母的大小写敏感(区分大小写)。变量名和函数名一般用小写字母+下划线,常量名和枚举名一般用大写字母+下划线,举例:

    变量:set_count
    函数:set_count()
    常量、枚举:SET_COUNT
    
  • C语言中有3类标识符:

    • 关键字:有32个,系统有特定含义和用途,不能用作自定义表示符:

      auto break case char const continue default do double else enum extern float for 
      goto if int long register return short signed sizeof static struct switch typedef 
      union unsigned void volatile while
      
    • 系统预定义的标识符:如系统提供的库函数名sim,printf,main,scanf等与处理指令include,define等。

      C语言中有12个预处理指令:

      define endif elif error line include ifdef ifndef pragma undef if else
      

      注意:以上预处理指令使用的时候,在前面需添加#,如#include

    • 用户表示符:用户定义的标识符,用来给程序的变量、自定义函数、符号常量、数组、构造类型、文件等命名。

    小提示:在C语言中,要求对所用到的变量,在使用前必须强制定义,即先定义,后使用

使用

  • 一个类型说明语句可以同时定义定义多个类型的变量,各个变量之间使用逗号分隔,多个同类型的变量也可以用多个类型说明语句定义:

    //写法一:一个类型说明可以同时定义多个类型的变量
    //优点:简洁
    //缺点:可读性较差
    int a,b,c,f,d; //定义多个同步类型的变量,这是一种简略写法
    int a1 = 3, b1 = 4, c1 = 5, d1 = 6;
    
    // 写法2:多个同类型的变量也可以用多个类型说明语句
    //优点:可读性强
    //缺点:繁琐
    int aa;
    int bb;
    int cc;
    int dd;
    int aa1 = 3;
    int bb1 = 4;
    int cc1 = 5;
    int dd1 = 6;
    
  • 同类型说明语句定义的变量只是说明了为这些变量分配了内存空间,一笔那鱼存放与之相同类型的数据,在未对这些变量赋值前,这些变量中的值是随机的(具体的随机由内存状态来决定),在C标准中访问未初始化的变量是“未定义行为(UB)”

    #include <stdio.h>
    int main(int argc,char *argv[])
    {
        int a,b,c,d;
        printf("%d,%d,%d,%d\n",a,b,c,d);// 此时的变量未初始化
    
        return 0;
    }
     // 第一次运行结果:1364676464,32767,0,0
     // 第二次运行结果:-829767712,32764,0,0
     // 经过测试发现,对未初始化的变量进行访问,访问的数据为随机数据
    
  • C语言允许定义变量的同时为变量赋初始值。

  • 在为长整型变量初始化或赋值时,如果被复制的数据为基本整型常量,则C编译系统自动被赋值数据转换为与之相依变量类型一致的数据。

    long a = 12L;//将一个int类型的常量12赋值给long类型的变量a
    
    long b = 12;//将一个int类型的常量12赋值给long类型的变量b,此时编译系统会自动将常量12的类型准换位long类型并赋值
    

在这里插入图片描述

  • 由于各种整型变量所占的字节数有限,因此,他们能存储的整数有一定的范围。

    举例::ugsigned char:1个字节,存储范围:0~255;char:1个字节,存储范围:-128~127

    在这里插入图片描述

基本类型数据

整型数据

用来存放整型数据的变量

我们定义一个整形的变量,C编译器实际是在内存中分配了能够在存储要给整型数据的存储空间。并用变量名标识这个空间,对该空间的使用也就是可以通过变量名来访问。(我们可以通过变量名访问变量空间

若不知道你所用的C编译系统对变量分配的存储空间的大小,可以通过sizeof运算符查询,如:

int a = 10;
printf("%d,%d\n",sizeof(int),sizeof(a));//4,4   sizeof返回的大小是以字节为单位的
整型数据在内存中的存储形式
  • 数据在内存中是以二进制补码形式存放

    如果有以下语句:

    shot i; //定义i为存储的整型变量  2字节
    i = 10

    则十进制数10的二进制形式为1010(十进制转转二进制,使用辗转相除法),则整数10在内存中的实际存储的形式为:

在这里插入图片描述

  • 实际上,数据在内存中是以补码的形式表示的,使用补码主要是为了统一加减运算,使CPU可以使用同一套加法电路处理所有整数运算(包括整数和负数),同时消除+0和-0的歧义,简化硬件设计。

    我们程序中数据直接转化出来二进制实际是原码形式的。

    • 正数的补码和原码(该数的二进制形式)相同的,(反码是原码和补码转换的过程产物)

    • 负数的补码是将该数绝对值的二进制形式,针对数据位按位取反+1(反码+1为补码)

在这里插入图片描述

内存数据的读写:

①向内存存数据(二进制形式):程序原始数据→二进制原码→二进制反码→二进制补码

②像内存取数据(二进制形式):二进制补码→二进制反码→二进制原码→程序原始数据

案例

需求:整型变量的定义和使用。

#include <stdio.h>

int main(int argc,char *argv[])
{
	// 定义有符号整型变量,可以存放正数、0、负数,默认就是有符号数。
	int a,b,c,d;// 等价于:signed int a,b,c,d;  一般不加signed
	
	// 定义无符号整型变量,可以存放正数、0,不能存放负数,必须添加关键unsigned
	unsigned int u;
	
	// 赋值
	a = 12;
	b = -24;
	u = 10;
    c = a + u, d = b + u;
    printf("a+u=%d,b+u=%d\n",c,d);// a+u=22,b+u=-14  
    // 注意:计算机硬件支持加法运算,不支持减法运算,我们程序中的减法运算,实际上是加法运算中的负数运算,比如:5-2实际上的实现 5+(-2)
    
    return 0;
 }

有符号和无符号数在内存中的存储形式(以char类型举例):

在这里插入图片描述

有符号char的范围:-128~127

无符号char的范围:0~255

浮点型数据

定义:用来表达实数(小数)的数据类型。

浮点型变量的分类
  • 单精度浮点型(float):在64位系统中尺寸是4字节,精确到小数点后位,格式化符%f
  • 双精度浮点型(double):在64位系统中尺寸是8字节,精确到小数点后15~16位,格式化符%lf
  • 长双精度浮点型(long double):在64位系统中尺寸是16字节。

注意:占用内存越多,能表达的精确度越高

float f1 = 12.25f; //单精度
double f2 = 12.5;  //双精度
long double f3;    //长双精度
浮点型

浮点型数据在内存中按照指数形式(IEEE754标准)存放。系统将一个浮点型数分为尾数部分指数部分,分别存放。

举例:

1234.5 → 1.2345 ∗ 1 0 3 → 1.2345 e 3 1234.5 → 1.2345*10^3 → 1.2345e3 1234.51.23451031.2345e3

类别符号位指数(指数部分)位数位(小数部分)指数偏移量
单精度浮点数1位[31]8位[30~23]23位[22~00]127
双精度浮点数1位[63]11位[62~52]52位[52~00]1023

float内存示意图
在这里插入图片描述

案例

  • 要求:写出27.5在内存中的存放形式

  • 解析:

    27.5的二进制为11011.1(正数部分辗转除2直到出现小数为止,小数部分辗转乘2直到出现0为止)

    转换为指数形式: 110111.1 → 1.10111 ∗ 2 4 110111.1 → 1.10111 * 2^4 110111.11.1011124

    指数:4+127 = 131,转换为二进制1000 0011

    尾数:10111,需要不够23位,应右侧补0:1011 1000 0000 0000 0000 000

    用二进制表示就是符号位(1位)、指数位(8位)、尾数位(23位),最终显示
    在这里插入图片描述

※科学计数法 ( 指数法 ) :

C语言中一般浮点数有两种表示形式:

  • 十进制形式:指的是数字必须以整数形式+小数形式组成,比如 10.0 、3.14 …符合规则, 以10为底数,并且科学计数法要在范围值之内。

  • 指数形式:一般数学上对于小数可以以10为底进行表示 比如3.14 * 10²,但是在使用英文 半角输入法的时候没办法输入上底或者下底,所以C语言规定以字母e或者E来表示指数,并 且要求字母e或者E的前面必须有数字,字母e或者E的后面必须为整数。 -3.14E-2 2E-3 0.3E4

printf("%e",10000000.00);

所以:E3 错误 因为E的前面有数据 比如说 3.14E3

​ 3.1e5.6 错误 因为 E的后面必须是整数

​ 3.1e-2 对的 相当于 3.1 ∗ 1 0 − 2 3.1*10^-2 3.1102

 1.01e-5 等价于  $1.01*10^-5$

字符型数据

概念:字符型变量用来存放字符常量

定义:

char 变量列表;

示例:

char a = 'A';
char b = a;  //A

范例:

#include <stdio.h>
int main(int argc,char *argv[])
{
    char c1,c2;
    c1 = 'A';
    c2 = 'B';
    
    printf("c1=%c\n",c1);// A %c是字符的格式化符号
    printf("c2=%c\n",c2);// B
    printf("c1=%d\n",c1);// 65
    printf("c2=%d\n",c2);// 66
    
    return 0;
}

运行结果:

在这里插入图片描述

说明:

一个字符变量只能存放一个字符。C编译系统规定以一个字节的存储空间来存放要给字符, 因此,一个字符型变量在内存中的大小是1字节( 1字符=1字节)

字符数据在内存中的存储形式

将一个字符常量存入一个字符变量,实际上并不是把该字符本身存入内存中,而是将该字符对应的ASCII码(系统内置)存入内存单元。

范例:

  • 需求:char c1 = 'a' , c2 = 'b'

  • 分析:

    • a的ASCII为97b的ASCII码为98,它们在内存中存放形式:

在这里插入图片描述

  • 进一步理解,实际上是按照二进制形式存放,形式为:
    在这里插入图片描述

由此可见 ,在内存中字符数据的存储形式与整型数据类似,这就使得字符型数据和整型数据之间可 以通用,也就是1个字符数据既可以以字符形式输出,也可以以整数形式输出。

  • 以字符形式输出时,编译系统将内存单元中的ASCII码转换为相应的字符,然后输出。
  • 以整型输出时,直接将ASCII码作为整数输出。
  • 因此,可以对字符数据进行算术运算,这时相当于对其ASCII码进行算术运算。

案例

  • 需求:大小写字母转换
  • 代码:
#include <stdio.h>
 
 int main(int argc,char *argv[])
 {
     char c1,c2;
     c1 = 97;// char既能赋值字符,也能赋值整数(ASCII码)
     c2 = 98;
 
     printf("%c %c \n",c1,c2);// a b, 以字符形式输出
     printf("%d %d \n",c1,c2);// 97 98, 以整数形式输出
 
     return 0;
 }

说明:char类型可以赋值为字符,也可以赋值为整数char a = 128,显示的结果范围:-128~127,计算规则:

char a = 值;
运行结果 = a的值 % 128

c1在内存的存储形式以及不同形式的输出,如下图所示:

在这里插入图片描述

案例

  • 需求:大小写字母转换
  • 代码:
#include <stdio.h>

int main(int argc,char *argv[])
 {
    char c1,c2;
    c1 = 'm';
    c2 = 'Y';
    printf("转换前:%c,%c\n",c1,c2);
    // 转换
    c1 = c1 - 32; // 赋值运算,运算规则:由右到左
    c2 = c2 + 32; 
    printf("转换后:%c,%c\n",c1,c2);
    return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值