1970年代初期,Dennis Ritchie编写了第一个C编译器。
在2017年,我想编写一个C编译器。诸如Deep C Secrets之类的书籍(Peter Van Der Linden)说,C首先是为了易于编译而设计的。但是我一直在遇到麻烦。
首先,要想出C语言的Lex / Yacc规范已经相对困难了,而当Ritchie制作他的编译器时,这些工具甚至还不存在!
另外,还有很多示例令人惊讶的小型C编译器,它们没有使用Lex&Yacc的任何帮助。(看看这个从法布里斯·贝拉。注意微小混淆的C编译器,他的“生产” tinycc源实际上相当长的时间是,最有可能在能够容纳更多的架构的努力,并成为更具可读性)
那我在这里想念什么?Ritchie在其编译器中使用了哪种词法分析器/解析器?有没有更简单的编写编译器的方法?
假设您使用Web Audio API来播放纯音:
ctx = new AudioContext();
src = ctx.createOscillator();
src.frequency = 261.63; //Play middle C
src.connect(ctx.destination);
src.start();
Run Code Online (Sandbox Code Playgroud)
但是,后来您决定停止声音:
src.stop();
Run Code Online (Sandbox Code Playgroud)
从现在开始,src现在完全没用了;如果您尝试再次启动它,您会得到:
src.start()
VM564:1 Uncaught DOMException: Failed to execute 'start' on 'AudioScheduledSourceNode': cannot call start more than once.
at <anonymous>:1:5
Run Code Online (Sandbox Code Playgroud)
比如说,如果您正在制作一个小型在线键盘,您就会不断地打开和关闭音符。从音频节点图中删除旧对象,创建一个全新的对象,然后connect()将其放入图中(然后稍后丢弃该对象)似乎非常笨重,而在需要时打开和关闭它会更简单。
Web Audio API 这样做有什么重要原因吗?或者是否有一些更干净的方法来重新启动音频源?
假设我用 C/C++ 编写了一个程序并希望允许加载插件。典型的解决方案是将插件编写为:
插件.c
int my_plugin_fn() {
return 7;
}
Run Code Online (Sandbox Code Playgroud)
并使用类似的东西编译它gcc -fpic -shared -o plugin.so plugin.c
然后,在加载这个插件的主程序中,我们可能有:
加载器.c
#include <stdio.h>
#include <dlfcn.h>
int main() {
void *plugin_handle = dlopen("./plugin.so", RTLD_LAZY);
if (!plugin_handle) {
printf("Could not open shared object: %s\n", dlerror());
return -1;
}
int (*fn)() = dlsym(plugin_handle, "my_plugin_fn");
char *err = dlerror();
if (err) {
printf("Could not resolve symbol: %s\n", err);
return -1;
}
printf("Plugin object returned: %d\n", fn());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用 编译了 loader.c gcc -o loader …
我正在阅读Micheal Abrash的图形编程黑皮书(顺便说一句,我很享受,我强烈推荐它),所以我正在使用的示例代码已经很老了.尽管如此,我不知道问题是什么:
__asm__(
//Some setup code here
"movl %%esi, %%edi;"
"movw %%ds, %%es;"
//A whole bunch more assembly code in between
"divloop:"
"lodsw;"
"divl %%ebx;"
"stosw;"
"loop divloop;"
//And a little more code here
: "=r" (ret)
: "0" (ret) /*Have to do this for some reason*/, "b" (div), "c" (l), "S" (p)
: "%edi", "%es"
);
Run Code Online (Sandbox Code Playgroud)
l变量是一个无符号int,则p变量是一个char*.l
是指向的字符串长度的字节数p.div
是除数,是一个无符号整数.ret是函数的返回值(无符号整数),并在程序段内部设置为除法的余数.我得到的错误消息是"错误:'asm'中的未知寄存器名'%es'"(这是唯一的错误消息).我最好的猜测是它在GAS语法中有另一个名字.我知道我正在使用旧代码,但据我所知,在我相当新的intel i3上仍然有一个ES寄存器被stos使用*
其次,有一个问题一直困扰着我.我基本上别无选择只能假设DS已经设置到正确的内存位置以便与lods*一起使用.由于我正在读取,修改和写入相同的内存位置(使用stos*和lods*),因此我将ES设置为等于DS.然而,我真的害怕我的DS可能是什么,我不知道还有什么可以设置它.更重要的是,ESI和EDI已经是32位寄存器,并且应该足以自己访问存储器.
根据我的经验,两个奇怪的问题通常是相关的,并且由更基本的问题(通常是PEBKAC)引起.但是,我在这一点上很难过.有谁知道发生了什么?
谢谢一堆
PS我正在尝试重新创建第9章(Hints My Readers Gave Me,清单9.5,第182页)中的代码,该代码通过EBX划分存储在连续内存中的大量数字.没有其他原因可以做到这一点,而不是我个人的成长和娱乐.
我有一个简单的小程序,可以将一种文件类型转换为另一种.fprintf()有很多调用(大致线性地依赖于要转换的文件的大小).当我开始时,没有调用fflush().在小文件(<10 Kb)上没有任何问题.在一个较大的文件(> 40 Kb)上,当达到fclose()的调用时,整个事情就崩溃了.
所以,我想也许我让缓冲区填满了太多东西,所以我在大约*512次调用fprintf(其中每个调用打印出8到10个字符)之后调用fflush().该程序仍然在调用fclose()时崩溃.
*因为我没有实际计数调用fprintf中,我用另算中已有的程序,有可能这个数字小于512.
这让我想到了我的问题.什么时候应该调用fflush()?应该在一定数量的数据被打印后调用吗?还是有什么我想念的?
谢谢
顺便说一句,如果它是相关的,我在Windows 7(64位)上,我已经在"a +"模式下输出文件
我的C ++代码中有一个具有自己的move构造函数的类。此处显示了简化版本:
class myClass {
//In this example, myClass must manually manage allocating
//and freeing a memory buffer.
char *mem;
//...
//Regular constructor, copy constructor, etc
//...
myClass(myClass &&other) {
//Swap our memory pointer with other's memory pointer
char *tmp = other.mem;
other.mem = mem;
mem = tmp;
}
//...
//Destructor, other member functions, etc.
//...
}
Run Code Online (Sandbox Code Playgroud)
在正常情况下,这可以正常工作。但是,最近我需要对这些对象进行向量处理:
vector<myClass> v;
v.reserve(10); //Make space, but do not construct
v.push_back(myClass()); //Problem!
Run Code Online (Sandbox Code Playgroud)
在经历了段错误并逐步使用gdb之后,我最终发现应该是显而易见的:如果尝试从右值引用构造对象,则可能导致在未初始化的内存上使用move构造函数。
当您有可能将垃圾交换到other类中时,应该如何编写move构造函数?有什么方法可以检测到这一点吗?
这是一个模糊的问题,因为我自己的理解也同样模糊。我感兴趣的是网络电缆上的零星电压需要发生什么才能导致计算机上运行的程序执行某些操作。
假设我在我的网络服务器上运行 apache2。有人在自己的联网计算机上触发了正确的事件序列,从而导致网络数据到达服务器。然后呢?
我的猜测是主板上有一些外围组件可以侦听数据,然后在 CPU 中引发中断。不知何故,在中断服务例程中,Linux 必须要求 apache2 代码做一些事情。这样对吗?如果是这样,有人愿意分享一些额外的细节吗?
谢谢
我正在阅读一篇关于rvalue-references的文章,但我对下面的摘录感到困惑:
X foo();
X x;
// perhaps use x in various ways
x = foo();
Run Code Online (Sandbox Code Playgroud)
这里,X是一些用户定义的类型.
我知道X foo();会调用X的构造函数,我很确定X x;不会.
但是,这条线x = foo();意味着什么?是否有一个名为?的构造函数?什么会x = foo;做?
尽我所能,我无法弄清楚要查找的正确单词以找出此代码的含义.