我反复讨论在GTK +代码中设置信号处理程序的问题,不需要几个参数,并试图使用与处理程序相同的函数来处理多个信号,其处理程序具有不同的签名 - 但是使用前N个参数(我关心的那些)同样的.
它是否安全(在某种意义上它不是未定义的行为,而不是更实用的"它在我的PC上工作吗?")将指针传递给GObject API,当这些函数期望参数少于它们时实际上是从信号发射过程中获得的?
或者,将此与GTK +离婚,这段代码还可以吗?
/* Note: No void *userdata argument! */
void show(int x) {
printf("x = %d\n", x);
}
void do_stuff(void (*fn)(int, void *), void *userdata) {
static int total = 0;
(*fn)(total, userdata);
total++;
}
void doitnow(void) {
do_stuff(&show, NULL);
}
Run Code Online (Sandbox Code Playgroud)
要获得额外的功劳,请讨论功能签名和呼叫站点之间不同返回值类型的含义.
编辑:一个几乎相同的问题更密切地探测"兼容的函数类型",并直接解决我的具体问题 - 链接GObject信号处理程序.TL; DR:是的,它是未定义的行为,但它在某些工具包中实际上是惯用的(尽管不是强制性的).
另一个共线点问题.这个问题是,我正在使用整数运算,我正在寻找精确的共线性,而不是基于模糊epsilon的测试.
使用内联汇编,我可以得到一个确切的答案:x86乘法指令可以访问产品的高低部分,这两者在计算叉积(X - A)x(B - A)时都很重要; 我可以简单地将这两个部分组合在一起并测试为零.但是我希望有一种方法可以用C来做,那就是:
大致按此顺序.同时,这样做的方法是:不是:
double关于X是否超出AB段,我不关心这个问题; 这只是四个无趣的比较.
我的噩梦是我必须将每个坐标组件分成两半,然后明确地进行长时间的乘法,这样我才能跟踪部分产品中的所有高半部分.(然后必须明确地使用add-with-carry.)
我正在研究我的gEDA分支,并希望摆脱现有的简单的基于区块的系统1,而不是真正的空间索引2.
有效地找到点的算法是不够的:我需要找到具有非零范围的对象.考虑具有边界矩形的对象,这几乎可以捕获索引中所需的细节级别.给定一个搜索矩形,我需要能够有效地找到其边界矩形在搜索矩形内部或相交的所有对象.
索引不能是只读的:gschem是一个原理图捕获程序,它的全部内容是在原理图中移动.所以事情将变得一团糟.因此,虽然我可以负担得起插入比搜索更昂贵,但它不能太昂贵,并且删除也必须既可能又合理便宜.但最重要的要求是渐近行为:如果不能是O(1),搜索应该是O(log n).插入/删除最好应为O(log n),但O(n)可以.我绝对不希望任何事情> O(n)(每个动作;显然O(n log n)是全对象操作的预期).
我有什么选择?我觉得不够聪明,不能评估各种选择.理想情况下会有一些C库可以为我做所有聪明的事情,但我会机械地实现一个算法,如果必须的话,我可能会或者可能不会完全理解.gEDA顺便使用glib,如果这有助于提出建议.
脚注:
1标准gEDA将原理图分为固定数量(当前为100个)的"瓦片",用于加速搜索边界矩形中的对象.这显然足以使大多数原理图足够快以进行搜索,但它的完成方式会导致其他问题:太多的函数需要指向事实上的全局对象的指针.瓷砖几何形状也是固定的:只要通过平移(并可能缩放)到仅由一个瓷砖覆盖的区域,就可以完全打败这种拼接系统.
2合理的答案是保留平铺系统的元素,但要解决其缺点:教导它跨越整个空间,并在必要时进行细分.但我希望其他人在我自我决定这是最好的方式之前加上他们的两分钱.
我有一个单行C函数return value * pow(1.+rate, -delay);- 它将未来值折现为现值.反汇编的有趣部分是
0x080555b9 : neg %eax 0x080555bb : push %eax 0x080555bc : fildl (%esp) 0x080555bf : lea 0x4(%esp),%esp 0x080555c3 : fldl 0xfffffff0(%ebp) 0x080555c6 : fld1 0x080555c8 : faddp %st,%st(1) 0x080555ca : fxch %st(1) 0x080555cc : fstpl 0x8(%esp) 0x080555d0 : fstpl (%esp) 0x080555d3 : call 0x8051ce0 0x080555d8 : fmull 0xfffffff8(%ebp)
虽然单步执行此函数,gdb说(速率为0.02,延迟为2;您可以在堆栈上看到它们):
(gdb) si 0x080555c6 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 …