我想在未来的某个时候建立一个操作系统,现在想一些关于它将如何的轻量级草图.我几乎已经在为Windows环境编译的C编码(和一些小Java).如果我想在Linux下运行它,我将不得不重新编译我的任何C程序.因此,对于每个操作系统,二进制文件(编译的产品)必须是不同的.如果我从头开始设计一个全新的操作系统,无论是业余爱好还是学术目的,都不使用Linux内核或操作系统的任何已知基本代码,我所理解的是,由于我的操作系统,我无法用GCC编译我的C程序不会是其目标系统之一.这里出现了关于标题的问题.提前感谢任何提示.
我在 C 中编写了仅包含头文件的小库和static-inline仅库。当应用于大型库时,这会是一个坏主意吗?或者是否有可能使用仅标头版本的运行时间会更快?好吧,不考虑明显的编译时间差异。
指定显式RGB颜色时,COLORREF值具有以下十六进制形式:
0x00bbggrr
低位字节包含红色相对强度的值; 第二个字节包含绿色值; 第三个字节包含蓝色的值.高位字节必须为零.单个字节的最大值为0xFF.
从 wingdi.h
#define RGB(r,g,b) ((COLORREF)((BYTE)(r) | ((BYTE)(g) << 8) | ((BYTE)(b) << 16)))
#define GetRValue(rgb) ((BYTE) (rgb) )
#define GetGValue(rgb) ((BYTE) ((rgb) >> 8))
#define GetBValue(rgb) ((BYTE) ((rgb) >> 16))
Run Code Online (Sandbox Code Playgroud)
由于windows是小端,COLORREF是RGBA格式.这看起来很奇怪,因为它不是Windows内部使用的颜色格式,BGR(A)?
的RGBQUAD结构被定义为
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
Run Code Online (Sandbox Code Playgroud)
这与COLORREFBGRA 不同.
由于bitblt函数需要一组COLORREF值,这意味着如果Windows使用BGRA作为其本机格式,则在每次调用期间总会有一个从RGBA到BGRA的额外转换.
我不记得了,但我也读到某处,在winapi中使用的像素格式有一种奇怪的混合.
有人可以解释一下吗?
我正在测试glDrawPixels使用GLFW将我的简单像素绘制2D游戏从Windows API移植到OpenGL。FPS可以在100多个跨平台上很好地运行。
令我有些烦恼的一件事是,我正在使用不推荐使用的功能。我现在看不到任何问题,但是将来可能会出现问题吗?可以glDrawPixels突然移走吗?我需要的是winapi CreateWindow和的跨平台替代方案BitBlt。
我们可以将特定签名的函数地址放入函数指针中,该函数指针被定义为具有其他签名并无缝使用吗?
例如,以下代码
#include <stdio.h>
void print_n(int *pn) {
printf("%d\n", *pn);
}
void print_n_wrapper(void *p) {
print_n(p);
}
int main(void) {
int n = 123;
void (*f)(void *) = print_n_wrapper;
f(&n);
f = print_n;
f(&n);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
得到编译并在我的机器上运行良好.我是以某种方式调用未定义的行为吗?
我对setjmp至少在x86_64 linux中究竟做了什么感兴趣,所以我搜索了glibc源代码,但我无法真正找到寄存器保存的位置.你能解释一下这里发生了什么吗?
SETJMP.H
extern int _setjmp (struct __jmp_buf_tag __env[1]) __THROWNL;
#define setjmp(env) _setjmp (env)
Run Code Online (Sandbox Code Playgroud)
BSD-_setjmp.c
int
_setjmp (jmp_buf env)
{
return __sigsetjmp (env, 0);
}
libc_hidden_def (_setjmp)
Run Code Online (Sandbox Code Playgroud)
setjmp.c
int
__libc_sigsetjmp (jmp_buf env, int savemask)
{
__sigjmp_save (env, savemask);
__set_errno (ENOSYS);
return 0;
}
weak_alias (__libc_sigsetjmp, __sigsetjmp)
stub_warning (__sigsetjmp)
Run Code Online (Sandbox Code Playgroud)
sigjmp.c
int
__sigjmp_save (sigjmp_buf env, int savemask)
{
env[0].__mask_was_saved = (savemask &&
__sigprocmask (SIG_BLOCK, (sigset_t *) NULL,
&env[0].__saved_mask) == 0);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 当我使用thread_local, _Thread_local, __thread, or 时__declspec(thread),编译器似乎在创建线程时分配一个线程本地存储,并将地址存储在 x86 派生系统中的fsorgs寄存器中。
在这种情况下,是否有“线程本地存储溢出”之类的东西?
我有一棵巨大的树,可能需要几千兆字节.节点结构如下.您会注意到我将最后一个成员设置为大小为1的数组.原因是我可以Node使用灵活的大小来过度分配.类似于C本身作为灵活阵列成员支持的内容.我可以使用std::unique_ptr<T[]>或std::vector<T>替代,但问题是,每个树节点有双重动态分配,双间接和额外的缓存未命中.在我的上一次测试中,这使我的程序花费了大约50%的时间,这对我的应用程序来说根本不可接受.
template<typename T>
class Node
{
public:
Node<T> *parent;
Node<T> *child;
/* ... */
T &operator[](int);
private;
int size;
T array[1];
};
Run Code Online (Sandbox Code Playgroud)
最简单的实现operator[]方式是这样.
template<typename T>
T &Node::operator[](int n)
{
return array[n];
}
Run Code Online (Sandbox Code Playgroud)
它应该在大多数理智的C++实现中正常工作.但是,由于C++标准允许疯狂的实现进行数组边界检查,因为我知道这在技术上调用了未定义的行为.那我可以这样做吗?
template<typename T>
T &Node::operator[](int n)
{
return (&array[0])[n];
}
Run Code Online (Sandbox Code Playgroud)
我在这里有点困惑.[]原始类型的运算符只是一个语法糖*.因此(&array[0])[n]相当于(&*(array + 0))[n],我认为可以将其清理为array[n],使一切与第一个相同.好的,但我仍然可以这样做.
template<typename T>
T &Node::operator[](int n)
{
return *(reinterpret_cast<T *>(reinterpret_cast<char *>(this) + offsetof(Node<T>, array)) + n);
}
Run Code Online (Sandbox Code Playgroud)
我希望我现在摆脱可能未定义的行为.也许内联汇编会更好地展示我的意图.但我真的必须走这么远吗?有人可以向我澄清事情吗? …
从随机地址读取安全吗?我知道写作是不确定的行为但是只读书怎么样?
好吧,在许多可视化调试器中,我可以在任意地址中看到内存的内容.这是怎么做到的?
通过值返回带有已删除副本构造函数的对象是否合法?例如,考虑具有std::unique_ptr成员的对象。大多数编译器在按值返回此类对象时不会抱怨,因为在大多数情况下,编译器甚至不会寻找副本构造函数。但是,由于标准不要求(N)RVO,因此可以说这些程序合法吗?是std::move在return语句为了在这些情况下,标准合规?