C语言-操作符详解(上)

C语言-操作符详解(上)

1、想获得浮点数结果,乘除数两个至少一个需要是float类型

2、在输出浮点型数据的时候需要“%f”

3、在输入数值的情况下如果不添加后缀f,编译器默认是双精度double类型。

4、在内存中开辟空间,内存单元的编号就是内存地址

&: 取地址操作符 地址是一组二进制的数字,以16进制来展示给开发者
int main(){
	int a = 10;
	printf("%p\n",&a);//& - 取地址操作符,且是起始内存单元的编号,int是四个字节那么从这个内存单元开始向后4个内存单元即是int a 的数据存储单元
	int *pa = &a;//pa是用来存放地址的 - pa就是一个指针变量,简而言之是将内存地址这个16进制数字存入这这个指针变量
    *pa;//* - 解引用操作符 - 间接访问操作符 就是根据pa中存储的地址找到这个地址中存储的对象。
    *pa = 20;//意思是将替换之前的值为20
	return 0;
}
//返回结果 00CFF9D4

强制类型转换();

sizeof()

//注意sizeof计算的是字节长度 比如arr是int 类型 一共10个元素 计算下来应该是4X10=40
//注意数组传参本质上是传输首元素的地址,所以调用的时候传的的首元素地址,结果是4或者8
#include <stdio.h>
void test1(int arr[])
{
	printf("%d\m",sizeof(arr));//(2)
}
void test2(char ch[]){
	printf("%d\m",sizeof(ch));//(2)
}
int main(){
	int arr[10] = {0};
	char ch[10] = {0};
	printf("%d\m",sizeof(arr));//(1)
	printf("%d\m",sizeof(ch));//(3)
	test1(arr);
	test2(ch);
	return 0;
}

比较两个字符串不能使用 ==

//例题 
int main(){
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;//在一开始就是否 后面就不用计算了 结果是1234
	//i = a++ || ++b || d++;
	printf("a = %d\nb=%d\nc = %d\nd = %d\n",a,b,c,d);
	return 0;
}

条件操作符(三目操作符)

//真前假后
int main(){
	int a = 3;
	int b = 0;
	if(a > 5)
		b = 1;
	else
		b = -1;
	//三目操作符
	b = (a > 5 ? 1 : -1);
	return 0;
}

逗号表达式

int main(){
	int a = 3;
	int b = 5;
	int c = 0;
	int d = (c = 5,a = c + 3, b = a - 4, c += 5);
	//逗号表达式 - 要从左向右一次计算,但是郑工表达式的结果是最后一个表达式的结果。
	return 0;
}

取模

1、取模两个数必须是整数,不能是0或者负数,没有意义

位移操作符

<< >>

1、简单来说这两个符号的尖头向那边就将整个二进制数列向那个方向移动

int a = 2;
//由于int类型是4个字节 一个字节8个bit,一共4X8=24个bit位 表示如下
00000000 00000000 00000010
int b = a << 1;
00000000 00000000 00000010
//相当于如果将这个二进制数列放入一个框体,尖头向哪里就向那个方向进行溢出。

源码、反码、补码

负数 :-1

存放在内存中

整数的二进制表示形式:其实有三种

源码:直接根据数据写出的二进制序列就是源码

反码:源码的符号位不变,其他位按位取反就是反码

补码:反码+1,就是补码

  • 逻辑移位和算数移位
    • 算数移位不改变正负号
    • 逻辑移位是改变最高位正负位的

位操作符

& | ^

^:相同为0 相异为1

这里首先需要明确 1 表示真 0表示假 然后按照与或非来进行逻辑运算即可

&
00000000 00000000 00000011	//3


交换数据使用位操作符的方法

单目操作符

sizeof(): 计算参数所占空间的大小,单位是字节

sizeof(s = a+2) 括号中的运算是不参与计算的。也就是说这里计算后的值用完就扔了

~a 对a按位取反

&取地址值符号

int main(){
	int a = 10;
	printf("%p\n",&a);//& - 取地址操作符
	int * pa = &a;//pa是用来存放地址的 - pa就是一个指针变量
	*pa;//* - 解引用操作符 - 间接访问操作符
	return 0;
}

下标引用、函数调用和结构成员

1、[]下标引用操作符

操作数:一个数组名+一个索引值

int arr[10];//创建数组
arr[9] = 10;//实用下标引用操作符
[ ]的两个操作数是arr和9

2、()函数调用操作符 接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

#define _CRT_SECURE_NO_WARNINGS 1
int main(){
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	//数组同下标来访问,下标从0开始
    printf("%d\n",arr[4]);//下标引用操作符的应用
	return 0;
}

3、()函数调用操作符

//函数的定义 
Add(int x, int y){
    return x + y;
}

void test(){
    
}
int main(){
	int a = 10;
	int b = 20;
//函数调用时传递的参数时原参数的拷贝,内存地址是不一样的。
	int ret = Add(a,b);
	test();//函数调用
	return 0;
}

4、访问一个结构的成员

.结构体.成员名


//结构成员访问操作符
//.
//->

//结构体
//
//int float char short
//double long
//
//书:书名,书号,出版社,作者,定价
//人:名字,年龄,性别
//

//创建了一个自定义的类型
struct Book{	//struct类似于java中的class
    //如下是结构体的成员或者成员变量
	char name[20];
    char id[20];
    int price;
};

int main(){
    int num = 10;
    //初始化方式与java不一样,java需要new 而且需要get set
    struct Book b = {"C语言","C20230322",55};
    
    printf("书名:%s\n",b.name);
    printf("书号:%s\n",b.id);
    printf("定价:%d\n",b.price);
    
    struct Book * pb = &b;
    //方法一 结构体变量名.成员名
    printf("书名:%s\n",(*pb).name);
    printf("书号:%s\n",(*pb).id);
    printf("定价:%d\n",(*pb).price);
    //方法二 结构体指针->成员名
    printf("书名:%s\n",pb->name);
    printf("书号:%s\n",pb->id);
    printf("定价:%d\n",pb->price);
    
    return 0;
}


表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定的。

同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

隐式类型转换

C的整型算数运算总是至少以缺省整型类型的精度来进行的。

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

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内存整型操作数的标准长度
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这中字节相加指令)。所以,表达式中各种长度可能小于int的整型值。都必须先转换为int或unsigned int 然后才能送入CPU去执行运算。
//实例1
char a,b,c;
...
a = b + c;

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

加法运算完成之后,结果将被截断,然后再存储于a中。也就是char只占1个字节多余字节扔掉再存到a中

int main(){
	//在bit位中首位是符号位
	char a = 3;
    //00000000000000000000000000000011
    //00000011 - a
	char b = 127;
    //00000000000000000000000001111111
    //01111111 - b
	char c = a + b;
    //00000000000000000000000000000011 + 00000000000000000000000001111111
    //=00000000000000000000000010000010
    //截断后10000010 - c
    //发现a和b都是char类型的,都没有达到一个int的大小
    //这里就会发生整型提升
    
	printf("%d\n",c);//%d需要打印整型,而此时c还是char需要进行提升
    //10000010 - c 符号位为1 高位补1为 11111111111111111111111110000010
    //高位为1 判断为补码 -1 取反
    //11111111111111111111111110000010 补码
    //11111111111111111111111110000001 -1变反码
    //10000000000000000000000001111110 符号位不变取反得到原码
    //打印 -126
	return 0;
}

如何进行整型提升呢?

整型提升是按照变量的数据类型的符号位来提升的

//负数的整型提升
char c1 = -1;
变量c1的二进制(补码)中只有8个比特位
11111111
/**
10000001//原码 符号位为1
11111110//反码 符号位不变其余取反
11111111//补码 末尾+1
*/
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
    
//正数的整型提升
cahr c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为char为有符号的char
所以整型提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//无符号整型提升,高位补0
//实例3
int main(){
    char a = 0xb6;
    short b = 0xb600;
    int c = 0x b6000000;
    if(a == 0xb6)	//提升a 后不等于0xb6
        printf("a");
    if(b == 0xb600)	//提升
        printf("b");
    if(c == 0xb6000000)	//本就是int 不需要提升
        printf("c");
    
    return 0;
}
//实例4
int main(){
	char c = 1;
	printf("%u\n",sizeof(c));//1
    printf("%u\n",sizeof(+c));//4
    printf("%u\n",sizeof(-c));//4
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值