在OCaml中,我如何以十六进制解析C99样式的浮点常量(作为文字或内部字符串),例如0x1.b000000000000p4
?
看起来它们不是有效的文字:
# let c = 0x1.b000000000000p4;;
Characters 12-27:
let c = 0x1.b000000000000p4;;
^^^^^^^^^^^^^^^
Error: Unbound record field b000000000000p4
Run Code Online (Sandbox Code Playgroud)
并且似乎没有Scanf
转换器来解析它们(例如,与C99的%a
转换器相对应printf
).
在OCaml中,当使用a let
为短路运算符(&&
或||
)分配别名时,它不再使操作数的评估短路.
这不直观.这种行为的原因是什么?
请考虑以下代码:
let f() = Printf.printf "f"; false;;
let g() = Printf.printf "g"; true;;
let a = (&&);;
f() && g();; (* outputs 'f' *)
(&&) (f()) (g());; (* outputs 'f' *)
a (f()) (g());; (* outputs 'gf' *)
Run Code Online (Sandbox Code Playgroud)
这也发生在let ... in
,let b = (&&) in b (f()) (g());;
也是输出gf
.
如何float
从字节数组中执行类似于此C技巧的操作以获取OCaml ?
union {
double d;
int i[2];
} u;
u.i[0] = 0;
u.i[1] = -20000000; // u.d = -0x1.ed3p+1005
Run Code Online (Sandbox Code Playgroud) 我想组装一个x86文件,同时确保代码将在给定的处理器上运行,而不必在处理器模拟器上进行测试.
是否有工具/技术允许我根据支持它的最老的所需处理器进行某种x86指令分类,或者至少在使用不兼容的指令时警告我?
简而言之,我正在寻找这个维基百科x86指令列表表的自动化版本,以帮助我检查给定代码是否应与给定处理器兼容.
阅读完C99标准后,我找不到任何禁止定义f
下面功能的部分:
struct s { double d; };
int f() {
if (0) return (struct s){.d = 3.14};
// There is intentionally no return statement of type int, which is valid
}
int main() {
f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
特别是,应该定义该程序的行为,因为返回值是(a)从未达到过的,并且(b)从未使用过,即使它已达到.
尽管如此,我的大多数编译器(GCC,Clang和CompCert)都会阻止编译此程序,但会出错returning 'struct s' from a function with incompatible result type 'int'
.我确实设法编译它tcc
,但我不知道它是否主要是由于运气(即缺乏验证).
有人可以确认这个程序在语法上是否有效C99,以及它的行为是否完全明确,或者说明标准禁止它的位置?
我实际上更喜欢我的编译器拒绝它,但是例如一些宏定义可以产生类似于这个的代码,所以如果它们是有效的,接受这些程序实际上是有用的.
背景
下面是我可以找到的C99标准的可能相关的摘录,以及我为什么不应该禁止我的程序在语法上有效和语义定义良好的原因:
§6.8.6.4退货声明
§6.8.6.4.1带有表达式的return语句不应出现在返回类型为void的函数中.不带表达式的return语句只能出现在返回类型为void的函数中.
在我的代码中,我们有一个void
非void
返回的非函数,所以一切似乎都很好.
§6.8.6.4.3如果执行带有表达式的return语句,则表达式的值将作为函数调用表达式的值返回给调用者.如果表达式的类型与其出现的函数的返回类型不同,则通过赋值给具有函数返回类型的对象来转换该值.
因为从不执行return语句,所以不适用.
§6.9.1函数定义
§6.9.1.12如果到达了终止函数的},并且调用者使用了函数调用的值,则行为是未定义的.
调用者不使用函数调用的结果,因此应该定义行为.
Printf模块API 详细介绍了类型转换标志,其中:
%B: convert a boolean argument to the string true or false
%b: convert a boolean argument (deprecated; do not use in new programs).
Run Code Online (Sandbox Code Playgroud)
但它没有说明为什么%b
被弃用。为什么%B
优于%b
?
我凭经验注意到通过 HTTPS (~500 KB/s) 和 SSH (>10 MB/s) 克隆 Github 存储库之间的显着带宽差异。
在发布周期中,我经常执行几个git clone
s,默认情况下配置为使用 HTTPS(如 ,git clone https://...
),因为它不需要身份验证并且对用户来说更简单。
但是,存储库包含大约 100 MB(由于多个版本、一些二进制文件等),因此由于带宽限制,此命令需要几分钟时间。如果我将git clone
命令更改为 use git://...
,它将以 10 MB/s 以上的速度下载,因此只需不到 10 秒。
理想情况下,存储库应该更小,但无论如何,我想通知用户这种差异,请他们参考官方文档,但帮助页面我应该使用哪个远程 URL?根本没有提到它,这个问题也没有。该速率限制规则不提任何带宽(和我在它们下面的方式,所以它不可能是问题)。
所以我想知道:这种行为对每个人来说都是已知的并且可以重现吗?我能看到一些特定的带宽限制git clone
吗(可能是在短时间内完成了几个s之后)?我想有一个官方来源来推荐用户。
在 OCaml 中,模式匹配中的顺序和性能之间有什么关系吗?
例如,如果我声明一个类型:
type t = A | B | C
Run Code Online (Sandbox Code Playgroud)
然后执行一些模式匹配如下:
match t1 with
| A -> ...
| _ -> ...
Run Code Online (Sandbox Code Playgroud)
从性能的角度来看,是否等价于
match t1 with
| B -> ...
| _ -> ...
Run Code Online (Sandbox Code Playgroud)
假设在第一种情况下,A 的数量与第二种情况中的 B 的数量一样多?
换句话说,在考虑性能时,我是否应该担心类型中构造函数的声明顺序?
我有一个旧脚本,其中包含 的变体sort +0 -1
,但man sort
在我的系统中甚至没有提到这些选项的存在。
从另一个问题,我被引导到 的维基百科页面sort
,上面写着:
在旧版本的排序中,该
+1
选项使程序使用第二列数据(+2
第三列等)进行排序。这已被弃用,相反,该-k
选项可用于执行相同的操作。
但它没有提到诸如此类的负面论证应-1
该做什么。
请注意,在我的“现代”排序(GNU coreutils 8.21)中,sort +0 -1
可以工作,而以下所有方法都会失败:sort +0 +1
、sort -0 -1
和sort -0 +1
。
我什至可以添加数字对(例如sort +0 -1 +2
,sort +0 -1 +2 -3
),但从一个简短的测试用例中我无法准确推断出它们的含义。
编辑:为了完整起见,现在无效的命令例如sort +0 +1
相当于sort -k1 -k2
.
在frama-C中,当我加载源文件时,它会进行预处理,并执行自动纠错,如"自动类型转换",如下所示(int被类型化为浮动).
现在,我如何才能看到预处理后所做的所有更改.
是否有任何方法或日志文件或警告消息显示frama-c所做的所有更改.这是我的源代码:
int main() {
int a, b;
printf("Input two integers to divide\n");
scanf("%d%d", &a, &b);
printf("%d/%d = %.2f\n", a, b, a/(float)b);
}
Run Code Online (Sandbox Code Playgroud)
这是我的frama-C预处理代码:
extern int (/* missing proto */ printf)();
extern int (/* missing proto */ scanf)();
int main(void) {
int a;
int b;
int __retres;
printf("Input two integers to divide\n");
scanf("%d%d", &a, &b);
printf("%d/%d = %.2f\n", a, b, (float)a/(float)b);
__retres =0;
return (__retres);
}
Run Code Online (Sandbox Code Playgroud)