我经常用C编程微控制器,因为C++编译器通常不可用,或者由于各种错误而无法制作极小的代码.但是,为了便于维护,OOP"语法糖"通常非常方便,因为它可以更加清晰地封装硬件程序.所以我想知道是否有办法在C中进行OOP语法,尽可能使OOP开销(在不需要时)以可移植的方式进行优化.例如:这将针对不同微控制器针对gcc进行优化,或者如果gcc不适用于该微控制器,则可能使用gcc的预处理器和通用ANSI-C编译器.
我发现只有线程,像这样,在C中进行OOP时,优雅的方式来模拟'this'指针?通常通过将指针嵌入到结构中来执行OOP,但这并不总是我想要的,因为当我对虚拟方法不感兴趣时,它会浪费内存,或类似的东西.我总是可以在需要这些功能的链接中遵循编码风格,但我想开发不需要它们的技术; 例如,我只是希望能够使用OOP范例进行编程,使用简单易懂的代码(不一定是C++,尽管我喜欢C++),并且当一些OOP范例不使用时仍然能够实现最小的C程序内存使用.
因此,我使用gcc和C99进行实验,因为一般来说gcc 3.2或更高版本适用于大多数平台; 并意识到我可以使用C99中的sizeof()和typeof()编译器函数自动索引类(来自未使用/未初始化的联合成员的"技巧")(所以类必须是带有子结构的联合),命令访问由宏创建的编译时常量查找表,它可以绑定数据和方法,并保证所有类型检查.等等
例如:GCC允许优化const结构和数组,当它们的成员只作为常量表达式访问时,所以我想我可以用它来构建一个基于宏的编译时绑定系统,其中处理OOP开销GCC实际上优化了最终的二进制文件.
使用这个系统,我现在可以进行可变宏方法调用,例如:M(a,init,"with","any","parameters",7)查找变量a的类型,调用方法init,使用变量number参数...
请参阅下面的代码示例,并尝试它们 - 它比解释简单:使用gcc -E查看宏扩展,并注意仅ANSI编译器,typeof()运算符必须替换为(void*)类型转换; 类型检查仅适用于GCC.
代码可以剪切并粘贴到文本编辑器中,文件名在第一行,它可以在普通的PC系统上编译和运行.
虽然我确实成功地摆脱了每个结构中的单个指针以"指回"一个类的方法列表,这可以节省有限内存微控制器中的内存,但我还是无法弄清楚如何让编译器进行优化out unused指针,因为我必须使用(void*)指针将类保存在数组中,这些指针需要一个内存地址(结构地址)和一个链接器实例; 并且不要优化.
所以:我想知道是否有人知道通过制作某种初始化的方法结构来改进我的解决方案的方法,该结构将在编译后优化(没有链接器地址),例如:当它的成员仅作为常量表达式访问时码.本质上,我需要能够在数组中查找元素,其中每个数组元素的初始化部分是不同的classXXX_mt,而不是所有类型为(void*)的classXXX_mt的地址列表.
如果有人能想到一个简单的解决方案,还有其他两个我需要帮助的改进; cpp(c-pre-processor)不允许通过标记连接从前一个宏中定义新的宏(据我所知),所以我必须制作固定长度的宏列表(在我的例子中最多10个) )持有类定义; 这意味着我在一个程序中最多只能有10个班级; 但理想情况下,我想要一种方法来使我的代码更通用,以便cpp可以动态创建可变长度列表.例如:问题与c预处理器无法自动"计数"有关.
其次,当我尝试为更新版本的GCC使用匿名结构时,我可能会删除访问ISO-C中的成员数据所需的额外"m",例如:foo.m.mydata,删除"m"从类联合定义中命名,并使用gcc -std = c11进行编译,然后它只是给了我错误声称结构定义没有...所以,即使在GCC 4.8中,联合内部的匿名结构也不起作用,尽管它应该; 我怎样才能让匿名结构起作用?
下面是我如何测试和实现包含文件voidbind.h的示例,该文件构建类列表并将方法静态链接到该类类型的变量.
最终,系统允许我像这个例子一样编程; 我用gcc 4.0到4.9编译没有问题:
//classtest.c
#ifndef MACROCHECK // Don't macro expand stdio.h, it's ugly...
#include <stdio.h> // to see macros, do gcc -D MACROCHECK -E classtest.c
#endif
#include "class1.h" // include example class, library.
#define _VOID_FINALIZE
#include "voidbind.h" // Make class list finalized, no …Run Code Online (Sandbox Code Playgroud) 我在Linux上有一个默认的vim安装,在一个带有vt52终端仿真器和unicode功能的系统上.
一切都工作正常,直到今天我将我的vt52 terminfo文件从临时本地用户目录移动到永久系统目录...起初看起来很好,但突然间,当我尝试通过按Enter键执行冒号命令(要么CTRL-J,或者键本身==十进制10),vim只是闪烁屏幕但不执行命令或离开命令输入模式.但是,如果我按下CTRL-M以获得回车符(十进制13),vim会接受该命令.
我尝试重新复制文件~/.terminfo,但它没有解决问题...
我认为这可能是一个tty问题或损坏的vimrc文件,所以...首先我尝试删除.viminfo和.vimrc文件,并stty sane在启动vim之前做一个但没有帮助.我只是注意到输入在插入模式下也不起作用,但CTRL-M确实如此.
然后我从bash shell中检查,使用CTRL-V,当我按下CTRL-M时,它显示^M,当我按下时CTRL-J,它只是输入并且什么也没显示.所以-仔细检查-我做了stty raw和cat - | hexdumpx,果然按下Enter键唯一回报0x0a,并按CTRL-M只有回报0x0d; 所以键盘驱动程序在原始模式下返回正确的字符,我在理智的模式下重新测试,显然将它们都映射到0x0A.
我用tic重新编译了termcap文件,并将其复制到~/.terminfo/v/vt52u以前工作正常的地方 - 然后复制到/usr/share/terminfo/v/vt52u.
但我没有在termcap文件中看到任何可能导致问题的内容.
vt52u|vt52 with UTF-8:\
:am:eo:rs=\Ee\Eb0\Eco:is=\EE\Ee:\
:nl=^j:sr=\EI:bl=^g:ta=^i:\
:ho=\EH:cr=^m:le=\ED:nd=\EC:do=\EB:up=\EA:ta=^i:nw=^j^m:xn:\
:cm=\EY%+ %+ :it#8:co#75:li#24:\
:sc=\Ej:rc=\Ek:\
:vi=\Ef:ve=\Ee:\
:so=\Eb0\Ec3:se=\Eb0\Eco:mh=\Eb8\Eco:mr=\Ebo\Ec0:me=\Eb0\Eco:\
:cl=\EH\EJ:cb=\Eo:cd=\EJ:ce=\EK:\
:km:kb=^h:
Run Code Online (Sandbox Code Playgroud)
编辑:我已经通过下面列出的实验5解决了这个问题,因为上面的termcap文件中有或者没有,或者是tic编译器将它转换为terminfo.
那么 - 什么termcap条目丢失或哪个现有条目导致问题?
----------------------我试图弄明白的其他实验-------------------
1::set term在vim中做一个揭示term=vt52u....这是正确的.所以VIM应该使用上面的termcap文件,但我不知道从哪里(例如:缓存版本,或者没有 - 或者已损坏.)和:version只显示+ termcap,表示vim应该使用tic编译的termcap文件这就是我一直想要的.
2:我重新编译了ncurses-5.9,并重新安装它以确保没有损坏的文件存在.即使有以下情况也没有改变 …
我(反复)遇到了各种公司的嵌入式 Linux 产品的问题,其中的 GPL 源代码与系统上实际运行的代码不匹配。它“接近”,但不太正确,特别是相对于他们使用的标准 C 库而言。这不是违反GPL吗?
通常,这种不匹配会导致程序员(像我一样)进行交叉编译,但在程序运行时设备却神秘地回复“找不到文件”或类似的信息。
我并不是唯一一个遇到此类问题的人 - 对于许多人来说,都有与该问题直接或间接相关的线程:例如: 基于 MIPS 的代码源工具链的编译参数?
我在 Sony 设备、D-link 和许多其他设备上都遇到过这个问题。这很常见。
制作新库并不是一个好的解决方案,因为大多数系统只是 ROMFS,并且 LD_LIBRARY_PATH 有时会损坏 - 因此在设备上安装新库会浪费非常有限的内存,并且通常无法工作。
如果我知道该库的正确源代码版本是什么,我就可以绕过制造商的粗心大意,并从原始开发人员树中编译它;但是,当我拥有的只是库本身的二进制文件时,如何找到我需要的版本?
例如:我在 DSL 调制解调器的 libc 上运行 elfread -a libc.so.0 (见下文);但我在这里没有看到任何可以告诉我它到底是哪个 libc 的内容......
如何从库的二进制文件中找到源代码的名称或标识符,以便我可以使用该库创建交叉编译器?例如:谁能告诉我这个库的源代码来自什么,以及他们是如何知道的?
ELF Header:
Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, big endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: …Run Code Online (Sandbox Code Playgroud)