对于大多数C/C++编译器,有一个可传递给编译器的标志-march=native,它告诉编译器调整生成的代码以用于主机CPU的微架构和ISA扩展.即使它没有使用相同的名称,通常也有基于LLVM的编译器的等效选项,例如rustc或swiftc.
根据我自己的经验,这个标志可以为数字密集型代码提供大量的加速,而且听起来它可以免于为你自己的机器编译的代码的妥协.也就是说,我认为我没有看到任何默认启用它的构建系统或静态编译器:
显然,任何要求您传递它的命令行编译器可执行文件都不会默认使用它.
我想不出任何默认启用它的IDE.
我想不出任何共同构建系统我已经与(工作的cmake,automake,cargo,spm,等),使其能够在默认情况下,即使是最优化的基础之上.
我可以想到一些原因,但没有一个真的令人满意:
使用-march=native不适合将分发给其他计算机的二进制文件.也就是说,我发现自己为自己的机器编译源代码比其他机器更频繁,这并不能解释它在调试版本中的缺乏用途,因为它没有分发的意图.
至少在Intel x86 CPU上,我的理解是不经常使用AVX指令会降低性能或功率效率,因为AVX单元在不使用时断电,要求它上电以供使用,以及许多Intel CPU下行运行AVX指令.尽管如此,它只解释了为什么不启用AVX,而不是为什么代码不会针对特定微架构处理常规指令而调整.
由于大多数x86 CPU使用具有寄存器重命名的花哨的无序超标量流水线,因此针对特定微架构的调优代码可能并不是特别重要.不过,如果它可以帮助,为什么不使用它呢?
有很多教程展示了如何在 Rust 中编写单元测试。我读过十几本书,所有这些都侧重于在成功的情况下维护价值观。对于error. PartialEq默认情况下,错误不会实现特征,因此您不能使用assert_eq!宏。此外,根据发生的问题类型(例如io::Error,可能是不同类型的),某些函数可能会返回多个错误变体。我可以检查是否发生了错误,但这似乎还不够。
下面举例。
fn parse_data(input: i32) -> Result<i32, io::Error> {
match input {
0 => Ok(0),
_ => Err(io::Error::new(io::ErrorKind::InvalidData, "unexpected number"))
}
}
#[test]
fn test_parsing_wrong_data() {
let result = parse_data(1);
assert!(result.is_err());
let got = result.unwrap_err();
let want = io::Error::new(io::ErrorKind::InvalidData, "unexpected number");
// compilation error here: binary operation `==` cannot be applied to type `std::io::Error`
assert_eq!(want, got);
}
Run Code Online (Sandbox Code Playgroud)
我认为这不是惯用的方法,因为它没有编译。因此,问题是 - 在类似情况下,什么是适当且惯用的方法?
我怎样才能把 aVec<u64>变成 a Vec<(&str, u64)>,使得前者的索引嵌入到str后者的部分中?
例如,[4, 9, 3]应该变成[("0", 4), ("1", 9), ("2", 3)].
我想这样做的原因是因为我想使用来自 TUI 的条形图绘制我的向量的条形图,这需要类似的类型。
我尝试了一些明显的事情,例如循环和推送:
fn main() {
let my_vec: Vec<u64> = vec![4, 9, 3];
let mut result: Vec<(&str, u64)> = Vec::new();
for (k, v) in my_vec.iter().enumerate() {
result.push((&k.to_string(), *v));
}
assert_eq!(result, [("0", 4), ("1", 9), ("2", 3)]);
}
Run Code Online (Sandbox Code Playgroud)
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:5:23
|
5 | result.push((&k.to_string(), *v));
| ^^^^^^^^^^^^^ - …Run Code Online (Sandbox Code Playgroud) 我想知道是否:
void *ptr = NULL;
printf("%p\n", ptr);
Run Code Online (Sandbox Code Playgroud)
会不会给出(nil)输出?
它是依赖于标准库实现,还是C99标准规范?
我有三个免费功能:F0,F1和F2.F0调用F1,然后调用F2.
F0和F2是C++函数,其中F1是C函数.F2通过以下方式暴露于F1:extern"C"
每个免费功能的代码如下:
~~~~ F0.cpp ~~~~
void f0()
{
try
{
f1();
}
catch (...)
{}
}
~~~~ F0.cpp ~~~~
~~~~ F1.c ~~~~
void f1()
{
f2();
}
~~~~ F1.c ~~~~
~~~~ F2.cpp ~~~~
void f2()
{
throw 1
}
~~~~ F2.cpp ~~~~
Run Code Online (Sandbox Code Playgroud)
题:
是否例外F2抛出的进展,通过F1和F0正确抓到?
或者由于未处理异常而调用std :: unexpected,或者整个事情应该是未定义的行为? - 如果是这样,它在标准中的哪个部分讨论了在这个特定环境中的异常处理.
请注意,这不是关于在C中处理异常,而是在异常可以流经C层(如果有的话)并被调用C++层捕获的情况下发生的情况 - 以及任何产生的副作用等.
我已经成功地用于serde_json反序列化和序列化 JSON。我的设置看起来有点像这样(非常简单):
use serde::{Deserialize, Serialize};
use serde_json;
use serde_with::skip_serializing_none;
#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Foo {
#[serde(flatten)]
bar: Option<Bar>,
baz_quux: Option<u8>,
}
#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
struct Bar {
#[serde(rename = "plughXyzzySomeRandomStuff")]
plugh_xyzzy: Option<u8>
}
Run Code Online (Sandbox Code Playgroud)
然后我实现了FromStrand Displayon Foo,它依次调用serde_json::from_str和serde_json::to_string,以轻松(反)序列化该结构。
但是,我现在还想支持serde_ini将 INI 文件序列化(反序列化)到相同的 Rust 数据结构。但我真的不知道该怎么做。
结构本身很简单,但我的具体问题在于属性:
#[serde(rename)]和#[serde(rename_all)]属性,但我不确定在哪里或如何解决。#[serde(flatten)] 似乎不适用于的serde_ini全字符串值,它需要#[serde(deserialize_with="from_str)]"所有非字符串值的属性,但这显然只适用于 INI 值,而不适用于 JSON 值。 …我已经搜索过但找不到任何结果(我的术语可能已关闭)所以请原谅我,如果以前曾经问过这个问题.
我想知道是否有一种简单的方法可以void*在不首先声明函数指针然后为函数指针分配地址的情况下调用C中的函数.
即.假设要调用的函数是typevoid(void)
void *ptr;
ptr = <some address>;
((void*())ptr)(); /* call ptr as function here */
Run Code Online (Sandbox Code Playgroud)
用上面的代码,我得到错误C2066:在VC2008中强制转换为函数类型是非法的
如果可能,具有返回类型和多个参数的函数的语法有何不同?
Debian系统上的C数学库的GCC实现显然符合(IEEE 754-2008)函数的实现,这意味着舍入应始终是正确的:exp
(来自维基百科)IEEE浮点标准保证加,减,乘,除,融合乘加,平方根和浮点余数将给出无限精度运算的正确舍入结果.对于更复杂的功能,1985年标准中没有给出这样的保证,它们通常只能在最后一点内准确到达.但是,2008标准保证符合要求的实现将给出正确的舍入结果,这些结果遵循主动舍入模式; 但是,函数的实现是可选的.
事实证明,我遇到了这个功能实际上阻碍的情况,因为exp函数的确切结果通常几乎恰好处于两个连续double值(1)之间的中间位置,然后程序进行了大量的进一步计算,失去了速度高达400(!):这实际上是对我的解释(不好问:-S)问题#43530011.
(1)更确切地说,当参数exp变为(2 k + 1)×2 -53,其中k为相当小的整数(例如242)时,就会发生这种情况.特别是,所涉及的计算pow (1. + x, 0.5)倾向于exp使用这样的参数进行调用x,其数量级为2 -44.
由于正确舍入的实现在某些情况下可能非常耗时,我想开发人员也会设计一种方法来获得稍微不那么精确的结果(例如,最多只有0.6 ULP或类似的东西)对于给定范围内的每个参数值(大致)有界限...(2)
......但是怎么做?
(2)我的意思是,我只是不希望像(2 k + 1)×2 -53这样的参数的某些特殊值比相同数量级的大多数值更耗时; 但是我当然不介意参数的某些特殊值是否更快,或者如果大参数(绝对值)需要更大的计算时间.
这是一个显示现象的最小程序:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
int main (void)
{
int i;
double a, c;
c = 0;
clock_t start = clock …Run Code Online (Sandbox Code Playgroud) 可以像这样传递一个整数数组:
const js = import("./webassembly_rust");
let array_nums = [1,2,3,4,5,6,7,8,9];
js.then(js => {
js.test( array_nums );
});
Run Code Online (Sandbox Code Playgroud)
到WebAssembly并将其保存在这样的向量中:
extern crate serde_json;
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[macro_use]
extern crate serde_derive;
#[wasm_bindgen]
pub fn test(array: JsValue) {
let elements: Vec<u32> = array.into_serde().unwrap();
}
Run Code Online (Sandbox Code Playgroud)
也可以像这样传递一个对象:
const js = import("./webassembly_rust");
let jsObject = {name: "hello world", id: "99", parent_id: "11"};
js.then(js => {
js.test( jsObject );
});
Run Code Online (Sandbox Code Playgroud)
到WebAssembly并将其保存为这样的Element结构:
extern crate serde_json;
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)] …Run Code Online (Sandbox Code Playgroud) 在标准库中,文档显示了如何实例化MaybeUninits的数组
:
let arr: [MaybeUninit<T>; N] =
MaybeUninit::uninit().assume_init();
Run Code Online (Sandbox Code Playgroud)
我们知道这是安全的,因为的合同MaybeUninit允许使用未初始化的值。接下来,我们被要求ptr::write(value)用来初始化每个元素。但这unsafe又需要代码。我们还知道覆盖a MaybeUninit是安全的,因为它没有drop任何作用。那么,为什么不覆盖它arr[i] = MaybeUninit::new(value)呢?