C语言表达式求值的两个细节和常见关键字

  

目录

  

表达式求值 

隐式类型转换

整型 提升

算数转换

常见关键字

关键字 typedef

关键字 static

define 定义宏


表达式求值 

隐式类型转换

整型 提升

C的整型算术运算总是至少以标准(int)整型类型的精度来进行的。

为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型 提升

char a,b,c;
...
a = b + c;

b和c的值被提升为普通整形,然后再执行加法运算

加法运算完成后,结果被截断,然后再储存于a中

意义

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度

一般就是int的字节长度,同时也是CPU的通用寄存器的长度。

因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长 度。

通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。

 

如何提升

//负数的整形提升

char c1 = -1;

变量c1的二进制位(补码)中只有8个比特位:

1111111

因为 char 为有符号的 char

所以整形提升的时候,高位补充符号位,即为1

提升之后的结果是:

11111111111111111111111111111111

//正数的整形提升

char c2 = 1;

变量c2的二进制位(补码)中只有8个比特位:

00000001

因为 char 为有符号的 char

所以整形提升的时候,高位补充符号位,即为0

提升之后的结果是:

00000000000000000000000000000001

//无符号整形提升,高位补0

#include<stdio.h>
int main()
{
	char a = 3;
    //000000000000000000000000000000000011 这是整型3的数据
    //00000011 这是变量a的数据形式
    //
	char b = 127;
    // 00000000000000000000000000001111111 
    //01111111 z\这是变量b的数据形式
	char c = a+b;
    
    //发现a和b都是char类型的,都没有达到一个int类型的大小
    //这里就发生了整形提升  整型提升 根据符号位来补1或者0
    //0000000000000000000000000000000000011 a
    //0000000000000000000000000000001111111 b
    //0000000000000000000000000000010000010 
    // c要截断变成char 类型         10000010  
	printf("%d\n", c);//输出为-126
    // 因为%d是表示打印整型,所以又会发生整形提升
    //111111111111111111111111111111 10000010
    //100000000000000000000000000000 01111110
    // 因为这个数是补码,所以表示的是-126
	return 0;
}

char a=0xb6,它是直接认为这串十六进制是补码,直接存储到内存

不会打印a和b,因为a和b在比较运算符时都会发生整形提升

0xb6是182   0xb600是46592

 a 10110110 经过整形提升 11111111 11111111 11111111 10110110 补码形式,

10000000 00000000 00000000 01001010 原码 输出  所以a以%d输出是-74

b 11111111 11111111 10110110 00000000补码 

   1000000 0000000 01001001 00000001 原码   b的-18689

int main()
{
 char c = 1;
 printf("%u\n", sizeof(c));//1
 printf("%u\n", sizeof(+c));//4
 printf("%u\n", sizeof(-c));//4
 return 0;
 }

表达式有两个属性  int a=4 int b=5 a+b 值属性9和类型属性 int

算数转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则就无法进行,下面的层次体系称为寻常算数转换

如果某个操作数的类型再上面列表的排名较低,那么首先转换为另一个操作数的类型后执行运算 

#include<stdio.h>
int main()
{/*
	char a = 3;
	char b = 127;
	char c = a+b;
	char a1 = 0xb6;
	printf("%d\n", a1);
	printf("%d\n", 0xb6);*/
	int a = 4;
	float f = 3.14f;
	printf("%f\n", a + f);//会发生算数转换 a会变成float类型
	return 0;
}

常见关键字

关键字 typedef

typedef 顾名思义是类型定义,这里应该理解为类型重命名。

#include<stdio.h>
typedef unsigned int u_int;
int main()
{
	unsigned int num = 100;
	u_int num2 = 100;//u_int 是unsigned int 的别名

	return 0;
}

关键字 static

1 修饰局部变量

2修饰全局变量

3修饰函数

修饰局部变量

改变了局部变量的生命周期(本质上改变了变量的存储类型),将数据从栈区放到了静态区

#include<stdio.h>
void test()
{
	int a = 1;//因为这是个局部变量。每次进函数都会重新赋值为1
	a++;
	printf("%d\n", a);
}
void test1()
{
	static int a = 1;//
	a++;
	printf("%d\n", a);
}
int main()
{
	
    int i = 0;
	while (i < 10)
	{
		test();//输出了10个2
		i++;
	}
    i = 0;
	while (i < 10)
	{
		test1();//输出 2 3 4 5 6 7 8 9 10 11
		i++;
	}
	return 0;
}

修饰全局变量

修饰全局变量使这个全局变量只能在自己所在源文件(.c)内部可使用

其他源文件不能用

全局变量,在其他源文件内存可以被使用,是因为全局变量具有外部链接属性

但是被static修饰后,就变成了内部链接属性,其他源文件就不能链接到这个静态的全局变量了

#include<stdio.h>
int g_val = 2022;
int main()
{
	
	printf("%d\n", g_val);//不能使用,因为是静态全局变量

	return 0;
}
#include<stdio.h>
static int g_val = 2022;

修饰函数

使函数只能在自己所在的源文件内部使用,不能再其他源文件使用

本质上static是将函数的外部链接属性变成内部链接属性,跟全局一样

#include<stdio.h>
//extern int g_val;
extern int Add(int x, int y);
int main()
{

	int a1= 10;
	int b1 = 20;
	int sum = Add(a1, b1);
	printf("%d\n", sum);
	return 0;
}

#include<stdio.h>
static int g_val = 2022;
 static int Add(int x, int y)
{
	return x + y;
}

无法使用这个static 修饰的函数 

define定义宏

define不是关键字

#include<stdio.h>
#define ADD(X,Y) X+Y
#define ADD1(X,Y) ((X)+(Y))
int main()
{
	
	printf("%d\n", 4*ADD(2, 3));//11 4*2+3 定义宏只是把ADD(2,3)变成了2+3;
    printf("%d\n", 4 * ADD1(2, 3));//20 
	return 0; 
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

库里不会投三分

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值