笔者记不住的一些注意事项和一些操作符的运用与君分享(基础C)

一.万恶的逗号表达式(逗号表达式所'要的是'最后一个值)

首先笔者对于要的是做了一个引号,😂,因为我自己无数次在这里犯错,我十分清楚逗号表达式对于所在表达式是只要最后一个值,但是往往会忘记前面的式子也会运算并将结果体现在后面的式子中。可能大家不太理解,我举个例子:

int main()
{
	//+的优先级高于+=
	int a, b, c;
	a = 5;
	c = ++a;//6
	b = ++c, c++, ++a, a++;//c=8,a=8,b=7  经典逗号表达式,这里就有坑,首先b=a++,其次这里运算后b应该等于7,前面的++a会使得a变成7,然后由于后面的a++是后置,所以b=7,而注意在后续运算中a=8了
	b += a++ + c;//a=9,c=8,b=23,a先以原本值参与计算再在后面的式子以a+1的值参与运算
	printf("a=%d,b=%d,c=%d\n", a, b, c);//9,23,8
}

这是比较经典的一道题,也是我摘录过来的。挺有意思的

二.让人迷糊糊的大端小端

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址 中; 小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地 址中。--每次读到定义我都很迷,就算理解了过两天就有分不清楚了。我按照自己浅薄的理解简要梗概一下。

小端存储是小的一端先存入低地址处,再依次向高地址处存放;"机器"在读取打印时是先打印高地址再打印低地址例如0x11223344  打印由高地址到低地址就是0x11223344,而在调试中是44332211(观者可以尝试)。

笔者简要绘制了一个图形:

 存储是 44 33 22 11 地址由低到高,进行更改也是由低到高。某度曾经出过如何检测机器是如何存储的。

这里给出两个方法:

1.常用方法

int main()
{
  int a=0x11223344;//验证是如何存储
  char*pc=(char*)&a;
  *pc=0;//由于强制类型转换只操作char*大小
  printf("%x\n",a);//%x代表是16进制
  return 0;
}

2.联合体方式

int check_sys()
{
 //采用联合体是借助联合体的特性来操作
 union
{
 int i;
 char c;
}un;
un.i=1;
return un.c;
}
int main()
{
 int ret=check_sys();
 if(ret==1)
 printf("是小端\n");
 else
 printf("是大端\n"); 
 return 0;
}

三.i是局部变量的话是随机值,全局变量不初始化默认是0;整形在和无符号数进行比较的时候,整形要转化成无符号数进行计算。

也用😳代码解释吧。

int i;
int main()
{
	i--;
	if (i > sizeof(i))//首先i全局变量默认是0,其次整形在和无符号数进行计算的时候要转换成无符号数参与计算,故-1特别大;
	{
		printf(">\n");
	}
	else
		printf("<\n");
    return 0;
}

输出为>

四.运算时容易忽略的整形提升

别忘了运算时的整型提升,对于非int型(cpu的通用寄存器长度)进行运算要进行整型提升,非整形数打印整形整型提升不够的位补符号位,
无符号位直接高位补零:
整型提升的例子:

int main()
{
	char a = 0xc6;
	short b = 0xc600;
	int c = 0xc6000000;
	if (a == 0xc6)
		printf("a");
	if (b == 0xc600)
		printf("b");
	if (c == 0xc6000000)
		printf("c");
	return 0;//只能打印出来c,因为a和b分别是char和short类型,所以在运算中会整型提升,发现值不再相等
}

第二大块:操作符的一些编码题目(有时操作符真的很有用,如果观者遇到一些考察"二进制的题目"而百思不得其解不妨想象底层的操作符,🌹)

1.统计二进制中1的个数

方法一:%2  /2  因为是二进制存储,故%2下来只有0和1两种情况。类似于十进制的。不过要注意%的对象只能是整形(笔者栽过坑)

int count_one_bit(unsigned int*get)
{
 int count=0;
 while(*get)
 {
  if(*get%2==1)
  {
   count++;
  }
   *get=*get/2;
 }
 return count;
 
}
int main()
{
 int get=0;
 scanf("%d",&get);
  int count=count_one_bit((unsigned int*)&get);//转化为unsigned int 的原因是因为如果仅仅整形,负数是无法计算的,故要转换
 printf("count=%d\n",count);
 system("pause");//停一下
 return 0;
}

2.法二

32个bit位,一个一个扣下来按位与&,右移操作符 按位与&

int count_one_bit(unsigned int*get)
{
int i=0;
int count=0;
for(i=0;i<32;i++)
{
if((*get)>>i&1==1)
count++;
}
return count;
}
int main()
{
int get=0;
scanf("%d",&get);
int count=count_one_bit((unsigned int*)&get);
printf("count=%d\n",count);
return 0;
}

3.法三(最优也是最难以理解)

//实现原理-以一个数字13为例
//1101    n
//1100-12 n-1
//n=n&(n-1),按位与后最右边1消失了
///1100 m --12
//1011(m-1)--11
//m与m-1 按位与后变为1000
//1000
//0111 按位与后变为0000
//n=n&n-1后就会让二进制序列里右边的1消失,执行几次就有几个1
int count_bit_one(unsigned int*get)
{
while(*get)
{
*get=*get&(*get-1);
count++;
}
return count;
}
int main()
{
int get = 0;
scanf("%d", &get);
int count = count_bit_one((unsigned int*)&get);
printf("count=%d\n", count);
return 0;
}

使用按位异或 ^
求二进制中不同位的个数
编程实现两个二进制数m和n中,有多少个位(bit)不同

int count_dif_bit(unsigned int*m,unsigned int*n)
{
	//先按位异或得到一个数,在进行求这个数有多少个1,即可解得
	int count = 0;
	unsigned int tmp = (*m) ^ (*n);
	while(tmp)
	{
		//用上文的最优解法
		tmp = tmp & (tmp - 1);
		count++;
	}
	return count;
}
int main()
{
	//避免代码冗余,直接设为无符号数类型
	unsigned int m = 0;
	unsigned int n = 0;
	scanf("%u%u", &m, &n);//%u是返回无符号数类型
	int count= count_dif_bit(&m, &n);
	printf("count=%d\n", count);
	return 0;
}

打印二进制的奇数位和偶数位
题目内容:获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出来

void Print(int* m)
{
	int i = 0;
	printf("奇数位:\n");
	for (i = 30; i >=0 ; i-=2)
	{
		//打印奇数位
		printf("%d ", (*m) >> i & 1);
	}
	printf("\n");
	printf("偶数位:\n");
	for (i = 31; i >=1; i -= 2)
	{
		//打印偶数位
		printf("%d ", (*m) >> i & 1);
	}
	printf("\n");
}
int main()
{
	int m = 0;
	scanf("%d", &m);
	Print(&m);
	return 0;//1011--00000000
}

这些内容是笔者希望分享给大家,让大家一样不再犯错。希望各位能有所收获吧!!🌹

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值