在我工作的项目中,我们有一些实用程序宏,它们多次引用它们的参数.
让我们用一个简单的例子:
#define ABS(a) ( (a) < 0 ? (-(a)) : (a) )
Run Code Online (Sandbox Code Playgroud)
现在这是一个很大的代码库,当我们检查代码时,我偶尔会发现一个函数调用被传递给宏.这不是错误,但它意味着多次进行函数调用,这通常是我不想要的.
在这种情况下,我们可以将其替换fabsf,fabs,abs用于float/ double/ int至少,但是让我们假设存在并不总是一个好的内置的更换和宏将留下一个宏.
例:
f = ABS(dot_v3v3(vel, sp));
/* expands into */
f = ( ( dot_v3v3(vel, sp) ) < 0 ? (-( dot_v3v3(vel, sp) )) : ( dot_v3v3(vel, sp) ) );
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:
是否可以检测宏内使用的函数调用(警告或错误)?
以下是我已经检查过的一些事情......
这将导致函数调用不编译,但缺点是像'1'这样的常量也会出现错误以及像(b-c)这样的表达式.
#define ABS(a) ((void)((&a) == (&a)), ( (a) < 0 ? (-(a)) : (a) ))
Run Code Online (Sandbox Code Playgroud)
注意:我发现这已经非常方便地指出了一些不好的宏用法,但由于它有误报,所以它不能留下来.
我正在尝试编写一个用于解构BSON数据的宏,如下所示:
let bson: Document = ...;
let (id, hash, name, path, modification_time, size, metadata, commit_data) = bson_destructure! {
get id = from (bson), optional, name ("_id"), as ObjectId;
get hash = from (bson), as String, through (|s| ContentHash::from_str(&s));
get name = from (bson), as String;
get path = from (bson), as Bson, through (PathBuf::from_bson);
get modification_time = from (bson), as UtcDatetime, through (FileTime);
get size = from (bson), as I64, through (|n| n as u64);
get metadata = from (bson), …Run Code Online (Sandbox Code Playgroud) 我有一个非常长的原始字符串文字.是否可以跨多行拆分它而不向字符串添加换行符?
file.write(r#"This is an example of a line which is well over 100 characters in length. Id like to know if its possible to wrap it! Now some characters to justify using a raw string \foo\bar\baz :)"#)
Run Code Online (Sandbox Code Playgroud)
例如,在Python和C中,您可以简单地将其写为多个字符串文字.
# "some string"
(r"some "
r"string")
Run Code Online (Sandbox Code Playgroud)
是否可以在Rust中做类似的事情?
\r在 Python 中,您可以使用移回行首在同一行上进行打印。
这对于进度条或增加百分比计数器非常有效,例如:Python print on same line
但是,当打印长度可能会减少的行时,这会将前几行文本保留在那里,例如:
import sys
for t in ['long line', '%']:
sys.stdout.write(t + '\r')
sys.stdout.write('\n')
Run Code Online (Sandbox Code Playgroud)
将终端文本保留为:%ong line。
打印到同一行时,在较长的行之后写较短的行的最佳方法是什么?
我很想知道它是否有可能在C中显式污染变量,因为它是未初始化的.
伪代码......
{
int *array;
array = some_alloc();
b = array[0];
some_free(array);
TAINT_MACRO(array);
/* the compiler should raise an uninitialized warning here */
b = array[0];
}
Run Code Online (Sandbox Code Playgroud)
下面是一种污染变量的方法的例子,但是当'a'被分配了未初始化的var而不是第二次使用'a'时,GCC会发出警告.
{
int a = 10;
printf("first %d\n", a);
do {
int b;
a = b;
} while(0);
printf("second %d\n", a);
}
Run Code Online (Sandbox Code Playgroud)
我能想出的唯一解决方案是使用未初始化的变量显式地隐藏变量,(添加空洞以便没有未使用的警告).
#define TAINT_MACRO_BEGIN(array) (void)(array); { void **array; (void)array;
#define TAINT_MACRO_END(array) } (void)(array);
{
int *array;
array = some_alloc();
b = array[0];
some_free(array);
TAINT_MACRO_BEGIN(array);
/* the compiler should raise an uninitialized warning …Run Code Online (Sandbox Code Playgroud) 关于vim的quickfix有很多文档,但我想知道:
我如何使用文本文件(或从终端复制+粘贴),并将其放入vim的快速修复列表中?
到目前为止我找到的所有文档都假设您运行make或者vimgrep,但在这种情况下,我只想使用在别处创建的文本文件.
说,我有一个具有可选功能的依赖项的箱子.现在这个功能主要用于测试,但是crate本身是整个代码的依赖.是否有可能指示货物仅将该功能用于测试?
在我的具体示例中,可选功能取决于quickcheck,我不一定希望对我的箱子用户强制依赖.
有一些旧的功能index,rindex现在已经被strchr和取代了strrchr.
有没有办法配置编译器或定义所以这些功能不可用?
在以下情况下,它可能会导致混淆警告
index范围之外的名称,例如 - 或者更糟,没有警告并以非预期的方式使用该功能.-Wshadow时会发出警告,如果您有一个名为的变量index.看到:
笔记:
index不应该重新定义,因为库可能会使用它.index.deprecated属性标记这些函数,因此与使用弃用函数相关的警告不起作用.有时我喜欢在函数中对相关变量进行分组,而不是声明新的结构类型.
在C中,这可以完成,例如:
void my_function() {
struct {
int x, y;
size_t size;
} foo = {1, 1, 0};
// ....
}
Run Code Online (Sandbox Code Playgroud)
在Rust中有办法做到这一点吗?如果不是,最接近的等价物是什么?
Vec支持std::io::Write,所以代码可以写成带有File或Vec,例如.从API参考,看起来既不Vec支持也不支持切片std::io::Read.
有没有方便的方法来实现这一目标?它是否需要编写包装器结构?
下面是一个工作代码的示例,它读取和写入一个文件,其中一行注释应该读取一个向量.
use ::std::io;
// Generic IO
fn write_4_bytes<W>(mut file: W) -> Result<usize, io::Error>
where W: io::Write,
{
let len = file.write(b"1234")?;
Ok(len)
}
fn read_4_bytes<R>(mut file: R) -> Result<[u8; 4], io::Error>
where R: io::Read,
{
let mut buf: [u8; 4] = [0; 4];
file.read(&mut buf)?;
Ok(buf)
}
// Type specific
fn write_read_vec() {
let mut vec_as_file: Vec<u8> = Vec::new();
{ // Write
println!("Writing Vec... {}", write_4_bytes(&mut vec_as_file).unwrap()); …Run Code Online (Sandbox Code Playgroud)