C++ 中文周刊 第98期

2023-02-25 10:50:19 浏览数 (1)

C 中文周刊 第98期

周刊项目地址


文章

  • Overview of C 23 Features

还是介绍c 23特性,鉴于中文资料还是比较少的,这里推荐一下

  • 严格别名(Strict Aliasing)规则是什么,编译器为什么不做我想做的事?

之前咱们也讲过很多次别名引入导致的性能低下,编译期不能充分优化的问题。这里又科普一遍,还有谁不知道?

  • 如何优化CPU GEMM?

simd指令教学,感兴趣的可以看看

  • Did you know that with gnu:C 26 a more parts of static reflection can be emulated?

https://godbolt.org/z/PPsn4KM7Y

简单来说还是embed,借助embed实现concept reflexpr

  • Getting in trouble with mixed construction

讨论optional各种构造转换

  • c 20 编译期解析(compile-time parsing)以及实现类似rust macro rule

https://godbolt.org/z/zKbWc7MhE

https://godbolt.org/z/5ajjYs754

直接贴代码了。很复杂,值得研究一波

  • Everything You Need to Know About std::variant from C 17

老文,讲了一些c 20的改进,比如constexpr

代码语言:javascript复制
#include <iostream>
#include <variant>

constexpr std::variant<int, double> foo(int x) {
    std::variant<int, double> oi { x * 0.1 };
    if (x > 10)
        oi = x;
    return oi;
}

int main() {
   constexpr auto dv = foo(1);
   static_assert(std::holds_alternative<double>(dv));
   constexpr auto iv = foo(100);
   static_assert(std::holds_alternative<int>(iv));
}

再比如经典坑

代码语言:javascript复制
std::variant<string, bool> x = "abc";   // 此时的x是bool,惊不惊喜

修订在这 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r3.html

  • Mixed C Monorepo Project Structure Development and Build Workflow

一些维护大项目的经验,比如ccache加速CICD,项目组织以及重用代码,甚至给了一个cmake模板 https://github.com/tfc/cmake_cpp_example

看着还不错


Raymond chen又发了一堆winrt的文章,我不了解,没细读,这里直接贴出来

  • Inside C /WinRT: Apartment switching: Bypassing the context callback
  • Inside C /WinRT: Apartment switching: Unblocking the outgoing thread
  • Inside C /WinRT: Apartment switching: The basic idea
  • Inside C /WinRT: Coroutine completions: The oversimplified version
  • How can I call a method on a derived class from a base class, say, to get a strong reference to the containing object?

  • 从零开始的算法竞赛Library制作·初衷和搭建环境

对OI感兴趣的可以看看,有几个模板库 比如这个https://github.com/emthrm/cp-library

  • 99 行代码写一个基于 Hyper-V 的 CPU 虚拟化执行

看个乐

  • LLVM Techniques 读书笔记

感兴趣可以看看

  • C 内存对齐

温故知新

[Daily bit(e) of C

Tree traversal algorithms](https://itnext.io/daily-bit-e-of-c-tree-traversal-algorithms-44e0d16bce08)

树的几种遍历,针对递归型,什么遍历,就在什么位置调用

如果是非递归用堆栈,前序遍历,那就堆栈里放left/right,后序遍历,那堆栈就放当前节点,中序遍历,那就先放left,放完了也就定好顺序了,访问节点和right就行了

我这里描述的非常模糊,边界条件也没说,不懂的话找个代码看看,我说个大概意思

  • Cursed C : Printing text with an empty main

在执行main之前还会执行别的动作。就是利用这个性质来打印。说实话一般

视频

  • C Weekly - Ep 360 - Scripting C Inside Python With cppyy

就是基于cling的一个python内调用c 的工具。cling有句讲句活跃程度堪忧

代码语言:javascript复制
>>> import cppyy
>>> cppyy.cppdef("""
... class MyClass {
... public:
...     MyClass(int i) : m_data(i) {}
...     virtual ~MyClass() {}
...     virtual int add_int(int i) { return m_data   i; }
...     int m_data;
... };""")
True
>>> from cppyy.gbl import MyClass
>>> m = MyClass(42)
>>> cppyy.cppdef("""
... void say_hello(MyClass* m) {
...     std::cout << "Hello, the number is: " << m->m_data << std::endl;
... }""")
True
>>> MyClass.say_hello = cppyy.gbl.say_hello
>>> m.say_hello()
Hello, the number is: 42
>>> m.m_data = 13
>>> m.say_hello()
Hello, the number is: 13
>>> class PyMyClass(MyClass):
...     def add_int(self, i):  # python side override (CPython only)
...         return self.m_data   2*i
...
>>> cppyy.cppdef("int callback(MyClass* m, int i) { return m->add_int(i); }")
True
>>> cppyy.gbl.callback(m, 2)             # calls C   add_int
15
>>> cppyy.gbl.callback(PyMyClass(1), 2)  # calls Python-side override
5

鉴于我们是c 周刊,python代码就不多列举了。大家感兴趣的自己玩玩

  • Harald Achitz: Lazy C , from deferred initialization as a type to operator().

我没懂,这种和经典singleton有啥不一样吗,哦singleton全局的

  • Cool stuff about GDB you didn’t know - Greg Law - Meeting C 2022

gdb结合tui,结合python等等,没总结,感兴趣的可以看看

  • [normalized Sound] A deep dive into dispatching techniques - Jonathan Müller - Meeting C 2022

ppt在这里 https://www.jonathanmueller.dev/talk/meetingcpp2022/

作者在搞一个脚本语言虚拟机,对比switch,改成jumptable带来很大受益,讲的就是这个调优过程

话说回来,不看视频只看ppt的话 https://meetingcpp.com/mcpp/slides/?year=2022 这里有挺有有意思的

比如这个 https://meetingcpp.com/mcpp/slides/2022/Basic usage of PMRs for better performance8308.pdf

我觉得非常值得一看

  • Just Enough Assembly for Compiler Explorer - Anders Schau Knatten - Meeting C 2022

我觉得还是直接看ppt吧,非常容易懂,我记得以前godbolt也讲过类似的主题

https://knatten.org/download/Anders Schau Knatten - Just Enough Assembly for Compiler Explorer - Meeting C 2022.pdf

我贴一下代码

代码语言:javascript复制
;--- 经典寄存器使用
mov rdi, 2
mov rsi, 4
add rdi, rsi
;结果 rdi 6, rsi 4

;--- 堆栈push/pop

mov rdi, 0xfedcba9876543210
push rdi
pop rsi

;结果 rsi=rdi=0xfedcba9876543210,经典赋值,两条指令,mov要多用一个寄存器/地址中转

;--- 访问地址

mov rsi, 0x3333333333333333
mov rdi, 0x2222222222222222
mov qword ptr [rsp - 8], rsi
add rdi, qword ptr [rsp - 8] 
;这里数组括号就是访问地址,把rsi弄到rsp-8的位置存一下,然后 add访问哪个地址的值,也就是rsi的值,加到rdi
; rdi 0x5555555555555555, rsi不变
; 为什么-8 因为rsi都是64位的寄存器
; byte: rax 8 eax 4 ax 2 al/ah 1

;来一个32位的例子

mov esi, 0x3333333333333333
mov edi, 0x2222222222222222
mov dword ptr [rsp - 8], esi
add edi, dword ptr [rsp - 8] 
;结果就不说了

;再来一个word例子

mov word ptr [rsp-8], 0x1111
mov word ptr [rsp-6], 0x2222
mov word ptr [rsp-4], 0x3333
mov word ptr [rsp-2], 0x4444
lea rdi, [rsp-8]              ; rdi指向rsp-8这个位置了
mov ax, word ptr [rdi 6]      ; ax 0x4444懂吧
mov rsi, 0
mov ax, word ptr [rdi rsi*2]  ; 0x1111
inc rsi
mov ax, word ptr [rdi rsi*2]  ; 0x2222

;---- 条件

 mov rsi, 2
 mov rdi, 3
 cmp rdi, rsi ;和j命令配合不满足继续走到jmp
 jg .greater
 mov rax, 0
 jmp .endif
.greater:
 mov rax, 1
.endif:

;---- 循环
; c代码这样
; int rax=0;
; for (int rcx=1;rcx!=3;  rcx) {rax  = rcx;}

 mov rax, 0
 mov rcx, 1
.for
 cmp rcx, 3
 je .endfor
 add rax, rcx
 inc rcx
 jmp .for
.endfor

;---- 来个函数
;int sum(int a, int b){ return a   b;}

sum(int, int):
  push rbp
  mov rbp, rsp
  mov DWORD PTR [rbp-4], edi
  mov DWORD PTR [rbp-8], esi
  mov edx, DWORD PTR [rbp-4]
  mov eax, DWORD PTR [rbp-8]
  add eax, edx
  pop rbp
  ret
;能看懂吧,另外优化后肯定能看懂,省掉把入参传到栈上来回折腾的流程了
sum(int, int):
  lea eax, [rdi rsi]
  ret

再来个例子,调用函数

;int times_two(int i);
;int sum_times_two(int a, int b){    return times_two(a   b);}
;int times_two(int i){    return i*2;}

sum_times_two(int, int):
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov DWORD PTR [rbp-4], edi
  mov DWORD PTR [rbp-8], esi
  mov edx, DWORD PTR [rbp-4]
  mov eax, DWORD PTR [rbp-8]
  add eax, edx
  mov edi, eax
  call times_two(int) ;看edi的用法
  leave
  ret
times_two(int):
  push rbp
  mov rbp, rsp
  mov DWORD PTR [rbp-4], edi
  mov eax, DWORD PTR [rbp-4]
  add eax, eax
  pop rbp
  ret

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

  • Announcing Dear ImGui Bundle 一个imgui周边整理工具包
  • Xmake v2.7.6 Released, Add Verilog and Cplusplus Module Distribution Support 强啊
  • gcl 有点像graphviz接口
  • catch2 3.3 支持测试用例跳过了,类似gtest的disable。

工作招聘

目前没看着有啥好工作,尽量别被开吧


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

如果有疑问评论最好在上面链接到评论区里评论,这样方便搜索,微信公众号有点封闭/知乎吞评论

代码语言:txt复制
     This site is open source. [Improve this page](https://github.com/wanghenshui/cppweeklynews/edit/dev/posts/098.md).

0 人点赞