循环展开是一种常见的优化,但反过来也是如此?
(减小目标文件输出的大小,更小的二进制).
我很好奇,如果编译器将连续的,相同的代码块(或函数调用)重复数据删除到循环中,或者将重复的块提取到静态函数中,这是一种常见的技术.
我很感兴趣,因为*C中只有一些头文件库可以添加大量重复代码,所以知道一些C编译器是否能够检测到这一点并更有效地处理它会很有用.
* 通过header-only-library,我的意思是直接定义代码而不是函数定义的头.
如果这样做,那么知道在什么条件和约束下适用以确保可以使用它将是有用的.
注意(出于问题的目的 - 任何流行的C编译器都是精细的GCC/Clang/Intel/MSVC).
我找到的一个只有头文件的库叫uthash使用了一些非常大的宏,我想知道是否有一些编译器技巧可以巧妙地去除这些巨大的代码块,参见:例如uthash.h,另一个类似的示例是内联qsort.h
可以重复数据删除的块的示例(事实证明它Py_DECREF可以扩展为相当大的代码块).
#define PY_ADD_TO_DICT(dict, i) \
do {
PyDict_SetItemString(dict, names[i], item = PyUnicode_FromString(values[i])); \
Py_DECREF(item); \
} while (0)
/* this could be made into a loop */
PY_ADD_TO_DICT(d, 0);
PY_ADD_TO_DICT(d, 1);
PY_ADD_TO_DICT(d, 2);
PY_ADD_TO_DICT(d, 3);
Run Code Online (Sandbox Code Playgroud)
请注意,这是设计的,但基于一个真实的例子.
似乎我的问题的简短答案是否定的(或仅在某些有限/微不足道的情况下),只是为了澄清我为什么要求进一步提问.
评论中的一些回复似乎假设任何人只需将代码重构为函数.当然,
这几乎总是最好的选择,但有时会出现非常相似的代码块.
在所有这些情况下,它可以去重复(生成更智能的代码,在函数中包装宏,修补第三方库),但在努力做这些事情之前,值得知道编译器为我们做了多少工作.
查找静态数组的大小是一种常见操作.看:C找到静态数组大小 -sizeof(a) / sizeof((a)[0])
这可以包装成一个宏,例如:
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
但是它可能会意外地传入常规指针.
例如: void func(SomeArray **foo) { int i = ARRAY_SIZE(foo); }
虽然它的有效C,但往往最终成为一个逻辑错误.
它可以防止这种错误(利用每个处理器在零长度位域上失败).
#define ARRAY_SIZE(a) \
((sizeof(struct { int isnt_array : \
((const void *)&(a) == &(a)[0]); }) * 0) + \
(sizeof(a) / sizeof(*(a))))
Run Code Online (Sandbox Code Playgroud)
我发现这个宏适用于GCC,但是对于间接引用的成员,它与Clang失败了.同error: expression is not an integer constant expression
例如:
char word[8]; int i = ARRAY_SIZE(word); 好.struct Bar { word[8]; } void func(struct Bar *foo) { int i = ARRAY_SIZE(foo->word); …使用过CMake之后,我已经习惯了使用CMake鼓励的源外构建.如何使用Cargo完成源外构建?
再次使用in-source-builds感觉就像倒退了一步:
Cargo.lock和target/,更糟糕的是,递归地暴露自己的内容.*.rs在target目录中添加文件作为构建间接deps的一部分,因此对所有*.rs文件进行操作可能会意外地拾取不在隐藏目录中的其他文件,因此即使在开发工具之后也不会被忽略已配置.虽然可以解决所有这些问题,但我宁愿只有一个外部构建路径并保持源目录的原始状态.
通过阅读这个帖子,看起来可以使用shebang来运行Rust*.
#!/usr/bin/env rustc
fn main() {
println!("Hello World!");
}
Run Code Online (Sandbox Code Playgroud)
使这个可执行文件运行并编译,但不运行代码.
chmod +x hello_world.rs
./hello_world.rs
Run Code Online (Sandbox Code Playgroud)
但是这只会将代码编译成hello_world.
可以*.rs文件可以直接执行,类似于一个shell脚本?
*这引用了rustx,我查看了这个,但是它是一个bash脚本,每次都编译脚本(没有缓存)并且永远不会从temp目录中删除文件,尽管这可以改进.它也有很大的局限性,它不能使用板条箱.
Rust过去一周我一直在玩弄.我似乎无法弄清楚如何在调用方法时传递一个被定义为参数的函数,并且没有遇到任何显示它们以这种方式使用的文档.
在调用函数时,是否可以在参数列表中定义函数Rust?
这是我到目前为止所尝试的......
fn main() {
// This works
thing_to_do(able_to_pass);
// Does not work
thing_to_do(fn() {
println!("found fn in indent position");
});
// Not the same type
thing_to_do(|| {
println!("mismatched types: expected `fn()` but found `||`")
});
}
fn thing_to_do(execute: fn()) {
execute();
}
fn able_to_pass() {
println!("Hey, I worked!");
}
Run Code Online (Sandbox Code Playgroud) 在C中定义结构时,有关于填充的注意事项,如果结构大小是一个问题,则通常重新排列值以避免填充.(参见:结构填料和包装)
我的问题是:
相同(或类似)的规则是否适用于函数参数?...在安排参数以避免参数填充字节方面有什么好处吗?
假设这不是inline(它不重要),或者static编译器可以重新排列参数的函数.
接受现实世界可衡量的改善可能很小.
...实际上,如果函数调用开销是一个问题,可能值得内联函数.尽管如此,内联并不总是一个选项(例如库或函数指针).
给定a std::path::Path,将此转换为空终止的最直接方法是std::os::raw::c_char什么?(用于传递到采用路径的C函数).
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_void;
extern "C" {
some_c_function(path: *const c_char);
}
fn example_c_wrapper(path: std::path::Path) {
let path_str_c = CString::new(path.as_os_str().to_str().unwrap()).unwrap();
some_c_function(path_str_c.as_ptr());
}
Run Code Online (Sandbox Code Playgroud)
有没有办法避免这么多中间步骤?
Path -> OsStr -> &str -> CString -> as_ptr()
Run Code Online (Sandbox Code Playgroud) 使用定义函数的宏时,是否可以为函数添加前缀?
macro_rules! my_test {
($id:ident, $arg:expr) => {
#[test]
fn $id() {
my_test_impl(stringify!($id), $arg);
}
}
}
Run Code Online (Sandbox Code Playgroud)
例如, fn my_test_$id() {
我正在使用可能以数字开头的标识符来定义测试,我想使用公共前缀.
有没有办法在Rust中打印出类型或实例的可用成员的完整列表?
如果问这个问题是Python,那么答案就是print(dir(object)).
如果问题是C,那么Clang有一个Python API可以解析C代码并对其进行内省.
不熟悉Rust工具,我很想知道是否有某种方法可以在运行时或编译时,使用编译器功能(例如宏)或使用外部工具来执行类似的操作.
请注意,这个问题是故意的,因为使用的确切方法不一定非常重要.给定一个变量,是否有办法找到它的所有方法和功能并不是一个不寻常的目标,但不能很好地了解这个领域,我不是将问题局限于特定方法.
假设有一个警告,例如path_statements,unused_variables.有没有办法忽略它的一个瞬间,而不将它们隔离成代码块或函数?
需要说明的是,代码中只有一个警告.我希望能够只安静警告,而不必针对特定警告进行特殊更改.并且在其他任何地方都没有这种安静的警告,甚至在同一个功能中也是如此.
使用GCC,可以按如下方式完成:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
/* Isolated region which doesn't raise warnings! */
this_would_raise_Wformat(args);
#pragma GCC diagnostic pop
Run Code Online (Sandbox Code Playgroud)
Rust具有相同的功能吗?
请注意,我正在询问如何安静警告的一般情况.我知道有办法解决未使用的var警告,例如.
rust ×7
c ×3
arrays ×1
build ×1
compilation ×1
ffi ×1
function ×1
macros ×1
optimization ×1
rust-cargo ×1
shebang ×1
string ×1
warnings ×1