在语义版本控制中,一般规则是仅在引入向后兼容功能时才增加次要编号,否则必须增加主要编号。将同样的方法,但使用不同的算法,是由使用的libtool。
我有一个问题,关于什么被认为是向后兼容的更改,什么不可以。
假设我已经编写了一个库,并且该库的公共标头包含一个typedef名为的数据类型foo。在1.0.0版中,这typedef看起来像这样:
typedef struct foo_t {
int x;
int y;
} foo;
Run Code Online (Sandbox Code Playgroud)
然后,我决定更改数据类型,在下一个版本中,它将看起来像这样:
typedef struct foo_t {
int x;
int y;
int z;
} foo;
Run Code Online (Sandbox Code Playgroud)
我仅在结构中添加了一个字段foo_t。这似乎是向后兼容的更改,但是上面的结构实际上是现在的另一种结构。我所做的并不是引入新功能,而其余所有功能都保持不变,而是我更改了已经存在的功能。
上面的数据类型通常用于与库的功能交换数据,但是用户可能已将其用于其他目的。如果用户使用1.0.0版编写了程序,而最后的更改构成了向后兼容的更改,则用户的程序也必须使用此新版本进行编译。
这个新版本如何命名为1.1.0或2.0.0?
编辑
您可以在此处阅读此讨论的进一步发展。
我有一个高度可移植的库(即使没有内核,它也可以在任何地方编译和运行良好),我希望它尽可能保持可移植性。到目前为止,我已经避免使用 64 位数据类型,但我现在可能需要使用它们 \xe2\x80\x93 准确地说,我需要一个 64 位位掩码。
\nuint64_t我从来没有真正考虑过它,而且我也不是一个足够的硬件专家(特别是在嵌入式系统方面),但我现在想知道:使用(或等效地)有什么不便uint_least64_t?我可以想到两种方法来解决我的问题:
有件事总是让我困惑va_end()。我经常读到这不是一个实际的函数,而是一个预处理器宏。尽管这听起来像是一个无关紧要的细节,但它实际上可能会影响va_end()需要调用的位置。
问题很简单:是否需要在具有多个语句的可变参数函数中的va_end()每个语句之前调用?returnreturn
NULL以下示例中的可变参数函数具有返回第一个非参数的简单任务。return正如你所看到的,函数体中有三个语句。其中之一出现在 之后va_start()但之前va_end()。
这段代码正确吗?
#include <stdio.h>
#include <stdarg.h>
static const void * const FIRST_NON_NULL_END = (void *) "";
void * first_non_null (
const void * const ptr1,
...
) {
if (ptr1) {
return ptr1 == FIRST_NON_NULL_END ? NULL : (void *) ptr1;
}
void * retval;
va_list args;
va_start(args, ptr1);
do {
retval = va_arg(args, void *);
if (retval == FIRST_NON_NULL_END) {
/* …Run Code Online (Sandbox Code Playgroud) 我有一个名为my_list包含链接列表的全局变量(即,该变量是指向列表的第一个成员的指针)。该变量只能由两个线程(线程 A 和线程 B)编辑。如果列表变空,则该变量将设置为NULL。发生这种情况时,首先将变量设置为NULL,然后释放内存。
由于它是由两个线程编辑的,因此每次线程 A 或线程 B 接触该my_list变量时我都会使用互斥锁。到目前为止没有什么异常。
但是接下来出现了第三个线程,线程 C。该线程永远不会以任何方式接触链表,但它需要不时知道链表是否为空。所以,线程C唯一要做的就是
if (my_list) {
do_something_completely_unrelated();
}
Run Code Online (Sandbox Code Playgroud)
我必须为此使用互斥体吗?我相信这是一个原子操作,因此不需要互斥体。它是否正确?
编辑
我将在这里添加一些背景信息。我想避免使用互斥体的原因是列表很少(总是)更新,但来自线程 C 的检查每隔几毫秒发生一次,因此操作越少越好。
如果列表显示为非NULL,则线程 C 会触发使用互斥锁的正确检查,并且如果确认列表不为空,则线程 C 停止其强制检查。
I am perfectly aware of the mechanism behind the switch statement and why an integer constant is required. What I don't undestand is why the following case label is not considered an integer constant. What is it then? A non-existing variable? Can anyone categorize it? Does the C compiler really need to be so dumb?
struct my_struct {
const int my_int;
};
switch (4) {
case ((struct my_struct) { 4 }).my_int:
printf("Hey there!\n");
break;
}
Run Code Online (Sandbox Code Playgroud)
And of course…
error: case …Run Code Online (Sandbox Code Playgroud)