• 什么是C语言常量?

    常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。常量可以是任何的基本数据类型。

    2小时前 22浏览
  • C语言中的可变参数

    C 语言允许您定义一个函数,能根据具体的需求接受可变数量的参数。

    昨天 51浏览
  • C语言中的文件读写

    我们讲解了 C 语言处理的标准输入和输出设备。本次我们将介绍 C 程序员如何创建、打开、关闭文本文件。

    昨天 36浏览
  • 常见的C语言操作寄存器玩法

    使用C语言对寄存器赋值时,常常需要用到C语言的位操作方法。

    昨天 44浏览
  • 如何启动STM32单片机?

    分享这篇文章,谈一下STM32启动流程。如果读者朋友已经有过汇编相关基础,能够够好理解本文内容。汇编

    03-13 183浏览
  • 判断奇偶数,if语句太多?教你一个简单高效的方法!

    看到这个标题,相信大多数人的第一反应是:真的有人用 40 亿条 if 语句,只为判断一个数字是奇数还是偶数? 的确有,这个开发者名为 Andreas Karlsson,他还把整个过程都整理成文了。 或许由于这“40 亿条 if 语句”听起来实在震撼,Andreas Karlsson 分享的这篇文章在 Hacker News 上很快引起了极大的关注和讨论,而他在文中也直白表示:其实这个想法,最初源于一个充满恶评的短视频。 以下为译文: 大于 11 的数字,没有输出结果 我最近在火车上刷手机时,偶然发现了上面这个截图:“写了一个程序,来判断一个数字是偶数还是奇数。”点开评论区,果然是一连串的恶意评论,多数都在嘲笑这位新手程序员的稚嫩和无知,竟企图以这种方式解决计算机科学中的经典问题“取模运算”。 可看过截图中的代码和网友评论后,我莫名生出了一些不同的想法:现在,AI 正在分分钟取代程序员、抢走他们的饭碗,并彻底改变了我们对代码的思考方式,或许我们应该更加开放地接受这个行业新生代的思想? 其实仔细想来,上述代码是时间和空间的一种完美权衡:你在付出自己时间的同时,也换来了计算机的内存和时间——这难道不是一个神奇的算法吗? 于是,我开始探索这种只使用比较来判断一个数字是奇数还是偶数的想法,看看它在实际情况中的效果到底如何。由于我是一位高性能代码的忠实拥护者,因此我决定用 C 语言来实现这个想法。 然后,我就开始编码了: /* Copyright 2023. All unauthorized distribution of this source code     will be persecuted to the fullest extent of the law*/ #include  #include  #include  int main(int argc, char* argv[]) {     uint8_t number = atoi(argv[1]); // No problems here if (number == 0) printf("even\n"); if (number == 1) printf("odd\n"); if (number == 2) printf("even\n"); if (number == 3) printf("odd\n"); if (number == 4) printf("even\n"); if (number == 5) printf("odd\n"); if (number == 6) printf("even\n"); if (number == 7) printf("odd\n"); if (number == 8) printf("even\n"); if (number == 9) printf("odd\n"); if (number == 10) printf("even\n"); } 接下来,我们要编译这段代码,使用 /Od 禁用优化,确保烦人的编译器不会干扰我们的算法。编译完成后,我们就可以对程序进行快速测试,看看结果如何: PS > cl.exe /Od program.c PS > .\program.exe 0  even PS > .\program.exe 4 even PS > .\program.exe 3 odd PS > .\program.exe 7 odd 结果显示:0、4 是偶数,3、7 是奇数。这么看来,程序似乎运行得挺好,但在进一步测试后,我发现了一些问题: PS > .\program.exe 50 PS > .\program.exe 11 PS > .\program.exe 99 大于 11 的数字没有输出,看来这个程序只对 11 以下的数字有效!回到原始代码中,可以发现问题出在最后一个 if 语句之后:我们需要更多的 if 语句! 向 32 位(32-bit)数扩展 这件事进行到这里,就需要我在时间和内存之间做出权衡了。考虑到我的寿命有限,我决定用另一种编程语言对 if 语句进行元编程。为了弥补这种“作弊”行为,我决定用“地球上速度最慢”的语言 Python。 print("/* Copyright 2023. All unauthorized distribution of this source code") print("   will be persecuted to the fullest extent of the law*/") print("#include ") print("#include ") print("#include ") print("int main(int argc, char* argv[])") print("{") print("    uint8_t number = atoi(argv[1]); // No problems here") for i in range(2**8):     print("    if (number == "+str(i)+")") if i % 2 == 0:         print("        printf(\"even\\n\");") else:         print("        printf(\"odd\\n\");") print("}") 好了!现在我们可以生成一个程序,解决所有 8 位(8-bit)整数的奇偶问题! PS > python programmer.py > program.c PS > cl.exe /Od program.c PS > .\program.exe 99 odd PS > .\program.exe 50 even PS > .\program.exe 240 even PS > .\program.exe 241 odd 看看,这个效果简直完美!现在,让我们把它放大到 16 位(16-bit)! print("    uint16_t number = atoi(argv[1]); // No problems here") … for i in range(2**16): 这样就得到了一个约 13 万行、超长且漂亮的 c 文件。回顾了一下我多年工作所做的一些代码库,这其实不算什么。话不多说,开始编译! PS > python programmer.py > program.c PS > cl.exe /Od program.c PS > .\program.exe 21000 even PS > .\program.exe 3475 odd PS > .\program.exe 3 odd PS > .\program.exe 65001 odd PS > .\program.exe 65532 even 太棒了,我们的算法似乎能够处理大量数据!可执行文件大约只有 2 MB,但这与我拥有高达 31.8 GB 内存的强大游戏设备相比,简直不值一提。 但众所周知,32 位(32-bit)才是计算机领域的终极目标,也是我们解决所有实际工程和科学问题所需的最终位宽。毕竟,在 IPv4 因所谓的 "地址耗尽 "而被认为过时 60 年后,它如今仍然很强大。所以,让我们来看看最终的规模:32 位的数字是 16 位的 65536 倍,这会有什么问题吗? print("    uint32_t number = atoi(argv[1]); // No problems here") … for i in range(2**32): 于是,我让强大的 Python 开始它的工作。48 小时后,我喝了一杯咖啡,然后回来检查程序,就得到了一个美丽的 c 文件,大小接近 330 GB!我几乎可以肯定,这是历史上最大的 c 文件之一。当我输入下一条命令时,我的手指都在颤抖,我猜 MSVC 肯定从未遇到如此强大的源代码。 在我那台可怜而强大的电脑页面文件中遭受半小时的折磨后,输出如下: PS > cl /Od program.c Microsoft (R) C/C++ Optimizing Compiler Version 19.32.31329 for x64 Copyright (C) Microsoft Corporation.  All rights reserved. program.c program.c(134397076): warning C4049: compiler limit: terminating line number emission program.c(134397076): note: Compiler limit for line number is 16777215 program.c(41133672): fatal error C1060: compiler is out of heap space 太令人失望了!不仅编译器让我失望,在研究 Windows 可移植可执行文件格式(.exe)的限制时,我发现它无法处理超过 4GB 的文件!由于需要将 40 多亿次比较语句编码到可执行文件中,这对于实现我们的算法是一个主要障碍。即使每次比较时使用的字节数少于一个,对我来说工作量也太大了。 不过,糟糕的编译器和文件格式不应该阻止我们实现梦想。毕竟,编译器所做的只是将一些花哨的机器代码写入文件,而文件格式只是一些结构,告诉操作系统如何将二进制代码放入内存——其实,我们自己就能做到。 解决最后一个问题,程序性能很不错 让我们先用 x86-64 汇编语言编写一个 IsEven 函数,因为这是我 Intel 处理器驱动的本地语言,它看起来是这样的: ; Argument is stored in ECX, return value in EAX XOR EAX, EAX ; Set eax to zero (return value for odd number) CMP ECX, 0h ; Compare arg to 0  JNE 3h ; Skip next two instructions if it wasn't equal INC EAX ; It was even, set even return value (1) RET ; Return CMP ECX, 1h ; Compare arg to 1 JNE 2 ; Skip next instruction if not equal RET ; Odd return value already in EAX, just RET ; add the next 2...2^32-1 comparisons here RET ; Fallback return 这并不是真正正确的汇编代码,但这不重要,因为我们要手动将其编译成机器代码。 你问我是怎么做到的?我上网查阅了x86(-64) 体系结构手册,还利用我早年编写仿真器和黑客经验,找出了每条指令的正确操作码和格式……开个玩笑,这是不可能的。实际上,我是直接问 ChatGPT 每条指令的正确操作码是什么,幸运的是,它也没有产生 x86-64 的任何新扩展。 所以现在我们只需编写一个“编译器”来输出这段代码。请注意,我们将直接使用从 AI 获取的指令操作码,下面是用 Python 编写的代码: import struct with open('isEven.bin', 'wb') as file:     file.write(b"\x31\xC0") # XOR EAX, EAX for i in range(2**32):         ib = struct.pack("

    03-05 256浏览
  • C语言入门必备,这份笔记你值得拥有!

    C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普

    03-05 238浏览
  • C语言中的结构体,你掌握了吗?教你如何定义和使用!

    C语言中数组允许定义可存储相同类型数据项的变量,结构是 C 编程中另一种用户自定义的可用的数据类型。

    03-05 212浏览
  • C语言:几个排序算法解析

    C语言中的排序问题。

    02-28 254浏览
  • C语言:强制类型转换解析

    强制类型转换是把变量从一种类型转换为另一种数据类型。

    02-28 178浏览
正在努力加载更多...
广告