前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >代码这么写,看起来比较像大佬

代码这么写,看起来比较像大佬

作者头像
TechFlow-承志
发布2022-08-26 16:03:03
5120
发布2022-08-26 16:03:03
举报
文章被收录于专栏:TechFlow

作者 | 梁唐

大家好,我是梁唐。

不知道大家有没有看过大佬编程呢?我印象最深的就是我第一次上acm赛场,acm赛场当中使用的都是Ubuntu系统的电脑。我就看到了前面几个清华的大佬熟悉地打开了vim,在漆黑的terminal当中上下飞舞,敲起了代码。

当时震撼的不行,脑子里反复的只有一个念头:什么是黑科技?这就是黑科技。

为此,我还特地学了一下如何使用vim编程,也开始了酷(装)炫(bi)生涯,比如经常在萌新面前露一手代码什么的。后来没过多久,我就发现赛场里大部分人都开始使用vim编程了,当然vim编程并不只是逼格高,也有一些其他的用处,比如编译运行比较快,字体也比较好看。

当然想要代码写的好看,有格调,只是换编译器是不行的,还需要在代码本身里面下点功夫。今天就和大家传授两招。

花括号的位置

首先最简单的一个就是花括号的位置,虽然大家都说花括号怎么写分成两派,一派喜欢另起一行,一派喜欢跟在代码后面。

但是根据我的观察,至少在国内, 这两派基本上都是按照实力划分的。说真的,我干这行这么多年,就没见过一个实力强劲且花括号换行的大牛。几乎无一例外都是紧跟在后的写法,实际上这样写代码主体会更短,看起来的确会比较舒服。

当年我还是一个萌新的时候,花括号一直是换行写的,直到入了acm的坑,看过了一些顶级选手的代码。发自内心地感叹,括号换行实在是太丑了。所以我个人会比较倾向建议萌新朋友们,可以试试这么写代码,当然这只是我个人的看法。

代码语言:javascript
复制
if (xxx && xxx) {
    
}

for (int i = 0; i < n; i++) {
    
}

while (xxx && xxx) {
    
}

位运算

如果说花括号还只是个人习惯的话,那么位运算绝对算是装逼利器。

根据计算机二进制存储数据的性质,我们将一个整数左移一位等价于将它乘以2,右移一位则等价于除以2。所以我们就可以使用左移和右移的位运算操作来代替乘以2、除以2的乘除操作。

比如在二分的时候,我通常会这么写:

代码语言:javascript
复制
while (l+1 < r) {
    int m = (l+r) >> 1;
    if (xxx) {
        l = m;
    }else {
        r = m;
    }
}

如果再结合或运算,那么乘以2+1的操作也可以玩出花,写成 <<1|1,也就是左移一位,再对1计算或运算。比如在一些树形数据结构当中,我们要求一个节点的左右叶子节点的时候,经常会用到乘2+1的操作。

另外一个很常用的是使用 1<<n 来代替2^n ,这也是赛场当中常见的惯用手段。

位运算的操作当然也不只是为了逼格,也是有一定的实际意义的。最大的意义就是运算速度快,实际上左移右移的运算是所有运算当中最快的,比加减运算还要快。而乘除相对来说要慢许多,尤其是除法是最慢的,比加减操作可能慢上几十倍。

有些计算量很大的题目,使用位运算和乘除运算得到的效率能差很多,就会导致明明使用的是同样的算法,但是别人通过了,你却超时了的尴尬情况。

memset

最后一个要说的就是memset,它是C语言当中对数组初始化的功能函数。

我贴一下它的源代码,其实非常简单,就是对一段连续内存进行赋值初始化。

代码语言:javascript
复制
void *(memset)(void *s, int c, size_t n) {
    const unsigned char uc = c;
    for (su = s; 0 < n; ++su, --n) {
        *su = uc;
    }
    return (s);
}

读一下源码就会发现,它虽然也是一个循环赋值的操作,但是它赋值的对象并不是数组当中的元素,而是字节(char)。这一点要千万注意,比如我们将一个数组初始化成0,我们只需要这样写就可以:

代码语言:javascript
复制
memset(a, 0, sizeof a);

之所以这样可以,是因为0是一个特殊值,以int型举例。C++当中一个32位的int占据4个字节,我们将每个字节赋值成0,那么所有这32位全为0,所以写成十六进制的话会是0x00000000,这个结果自然就是0。

同样我们初始化成-1也是可以的,因为-1的补码全为1。初始化结束之后得到的每一个二进制位都是1,转化成十进制仍然是-1。

如果我们传入的不是0,也不是-1,就会有问题,比如我们假设传入的是3,那么初始化之后这个int就会变成0x03030303,这个数转成十进制显然不是3。所以我们想要通过memset将数组初始化成最大,可以传入0x7f,7f是8位二进制能够表示的最大正整数,使用7f初始化之后得到的int为0x7f7f7f7f,非常接近最大的正整数0x7fffffff。

不过一般比赛的时候,我用得比较多的都是0x3f,这样初始化得到的结果大约是最大整数的一半不到。这样的好处是可以保证当需要两个最大值相加的时候,它们的和也不会超过int范围。

最后做个简单的总结,当你需要对int型的数组初始化的时候,可以这么写:

代码语言:javascript
复制
int a[10000];

memset(a, 0, sizeof a); // 将a全赋值成0
memset(a, -1, sizeof a); // 将a全赋值成-1
memset(a, 0x7f, sizeof a); // 将a全赋值成0x7f7f7f7f7f,接近最大int

好了,这些提升代码逼格的小技巧,你学会了吗?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-09-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 花括号的位置
  • 位运算
  • memset
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档