小编Joh*_*nck的帖子

C中的&*NULL定义良好吗?

C标准的哪个版本(如果有的话)是如何明确定义的?

void foo(void) {
    char *nullPtr = NULL;
    &*nullPtr;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我没有将结果分配给任何东西 - 第二行是一个简单的语句.

应该是一个有明显答案的问题,但是(就像在这些问题上看似经常发生的那样)我听到的同样有很多人说答案"明显未定义"为"明确定义".

在一个相当相关的说明,以下是什么?应该foo产生一个c?

extern volatile char c;

void bar(void) {
    volatile char *nonnullptr = &c;
    &*nonnullptr;
}
Run Code Online (Sandbox Code Playgroud)

(相同问题的C++版本:在C++中是否&*NULL定义良好?)

c language-lawyer

25
推荐指数
1
解决办法
1448
查看次数

GCC优化错失了机会

我正在编译这个C代码:

int mode; // use aa if true, else bb
int aa[2];
int bb[2];

inline int auto0() { return mode ? aa[0] : bb[0]; }
inline int auto1() { return mode ? aa[1] : bb[1]; }

int slow() { return auto1() - auto0(); }
int fast() { return mode ? aa[1] - aa[0] : bb[1] - bb[0]; }
Run Code Online (Sandbox Code Playgroud)

两者slow()fast()函数都是为了做同样的事情,尽管fast()它有一个分支语句而不是两个.我想检查GCC是否会将两个分支机构合并为一个分支机构.我已经尝试了GCC 4.4和4.7,具有各种级别的优化,如-O2,-O3,-Os和-Ofast.它总是给出同样奇怪的结果:

慢():

        movl    mode(%rip), %ecx
        testl   %ecx, %ecx
        je      .L10

        movl    aa+4(%rip), %eax
        movl    aa(%rip), …
Run Code Online (Sandbox Code Playgroud)

c optimization x86 assembly gcc

24
推荐指数
2
解决办法
1072
查看次数

为什么C++ 11强类型枚举不能通过指针强制转换为底层类型?

在C++ 11中,我们可以将强类型的枚举(enum class)强制转换为其基础类型.但似乎我们不能指向相同的指针:

enum class MyEnum : int {};

int main()
{
  MyEnum me;

  int iv = static_cast<int>(me); // works
  int* ip = static_cast<int*>(&me); // "invalid static_cast"
}
Run Code Online (Sandbox Code Playgroud)

我试图理解为什么会这样:有什么关于枚举机制的东西让支持这个很难或没有意义吗?这是标准中的简单疏忽吗?别的什么?

在我看来,如果枚举类型真正构建在如上所述的整数类型之上,我们应该不仅能够投射值而且还能投射指针.我们仍然可以使用reinterpret_cast<int*>或者使用C风格的演员表,但这比我认为的更重要.

c++ enums c++11 enum-class strongly-typed-enum

24
推荐指数
4
解决办法
7449
查看次数

GCC无法像C阵列一样优化对齐的std :: array

以下是GCC 6和7在使用时无法优化的一些代码std::array:

#include <array>

static constexpr size_t my_elements = 8;

class Foo
{
public:
#ifdef C_ARRAY
    typedef double Vec[my_elements] alignas(32);
#else
    typedef std::array<double, my_elements> Vec alignas(32);
#endif
    void fun1(const Vec&);
    Vec v1{{}};
};

void Foo::fun1(const Vec& __restrict__ v2)
{
    for (unsigned i = 0; i < my_elements; ++i)
    {
        v1[i] += v2[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

编译上面的g++ -std=c++14 -O3 -march=haswell -S -DC_ARRAY代码会产生很好的代码:

    vmovapd ymm0, YMMWORD PTR [rdi]
    vaddpd  ymm0, ymm0, YMMWORD PTR [rsi]
    vmovapd YMMWORD PTR [rdi], ymm0 …
Run Code Online (Sandbox Code Playgroud)

c++ optimization gcc simd memory-alignment

24
推荐指数
1
解决办法
3914
查看次数

使用GNU Readline; 如何在同一个程序中添加ncurses?

标题比我的实际目标更具体:

我有一个命令行程序,它使用GNU Readline,主要用于命令历史记录(即使用向上箭头检索以前的命令)和其他一些细节.现在,程序的输出中间散布着用户的输入,有时候输出是正常的,但输出是异步的(它是通过网络连接来响应输入命令),有时会变得烦人(例如,如果用户输出行时)正在输入新的输入).

我想为这个程序添加一个功能:输出的单独"窗口".我想过为此使用ncurses.但是从ncurses FAQ中可以看出,这两个库并不容易一起使用.

我可能会考虑使用Editlinetecla而不是Readline,但我不清楚其中任何一个是否能解决我的问题.我还考虑使用除ncurses之外的其他东西,包括提供两种功能的库(文本模式窗口和命令历史记录),但我不知道什么是最好的.

哦,对彩色文字的支持可能会得到奖励积分.我怀疑我可能能够做到这一点与Readline库,所以也许这是一个单独的问题,但如果我的问题的解决方案也可以轻松一点颜色添加到输出,那就更好了.

我正在使用Ubuntu Hardy(Linux 2.6).

ncurses readline editline

22
推荐指数
3
解决办法
6711
查看次数

是 GCC 错误编译了这段代码,还是 UB 错误编译了这段代码?

考虑这段代码:

#include <cstring>

template<typename T>
struct DefaultMsgImpl
{
    DefaultMsgImpl() { memset(this, 0, sizeof(T)); }
};

struct Msg : DefaultMsgImpl<Msg>
{
    int num;
};

int f()
{
    Msg msg{.num = 66};
    return msg.num;
}
Run Code Online (Sandbox Code Playgroud)

对于 GCC 13(及更早版本),f()返回 0,但对于所有其他编译器(MSVC、Clang、ICC、ICX...),f()返回 66。

上面的代码是有效的C++(在这种情况下,GCC 似乎对其进行了错误编译),还是未定义的行为(例如,因为 memset 在 的生命周期开始Msg之前接触了内存)?T如果是 UB,我希望得到引用 C++ 标准的答案。

演示: https: //godbolt.org/z/1qf9dv8cG

c++ gcc language-lawyer

22
推荐指数
1
解决办法
459
查看次数

派生类中的静态方法可以在C++中调用受保护的构造函数吗?

这段代码适用于clang,但g ++说:

错误:'A :: A()'受到保护

class A
{
protected:
    A() {}
};

class B : public A
{
    static A f() { return A(); } // GCC claims this is an error
};
Run Code Online (Sandbox Code Playgroud)

哪个编译器是对的?

c++ static constructor compiler-errors protected

21
推荐指数
1
解决办法
1534
查看次数

返回比std :: pair更低效的2元组?

考虑以下代码:

#include <utility>
#include <tuple>

std::pair<int, int> f1()
{
    return std::make_pair(0x111, 0x222);
}

std::tuple<int, int> f2()
{
    return std::make_tuple(0x111, 0x222);
}
Run Code Online (Sandbox Code Playgroud)

Clang 3和4在x86-64上生成类似的代码:

f1():
 movabs rax,0x22200000111
 ret    
f2():
 movabs rax,0x11100000222 ; opposite packing order, not important
 ret    
Run Code Online (Sandbox Code Playgroud)

但是Clang 5生成了不同的代码f2():

f2():
 movabs rax,0x11100000222
 mov    QWORD PTR [rdi],rax
 mov    rax,rdi
 ret    
Run Code Online (Sandbox Code Playgroud)

正如GCC 4至GCC 7一样:

f2():
 movabs rdx,0x11100000222
 mov    rax,rdi
 mov    QWORD PTR [rdi],rdx ; GCC 4-6 use 2 DWORD stores
 ret
Run Code Online (Sandbox Code Playgroud)

返回std::tuple适合单个寄存器的生成代码为什么会更糟std::pair?看起来特别奇怪,因为Clang 3和4似乎是最优的,而5则不是.

在这里试试:https: …

c++ gcc clang calling-convention stdtuple

21
推荐指数
1
解决办法
1474
查看次数

程序终止时保证文件删除(C/C++)

Win32 CreateFileFILE_FLAG_DELETE_ON_CLOSE,但我在Linux上.

我想打开一个临时文件,在程序终止时将永远删除该文件.我可以理解,在程序崩溃的情况下,保证这一点可能不切实际,但在任何其他情况下我都希望它能够工作.

我知道RAII.我知道信号.我知道atexit(3).我知道我可以打开文件并立即删除它,文件将保持可访问状态,直到文件描述符关闭(甚至处理崩溃).这些似乎都不是一个完整而直接的解决方案:

  1. RAII:去过那里,完成了:我有一个析构函数删除文件的对象,但如果程序被一个信号终止,则不会调用析构函数.
  2. 信号:我正在编写一个低级库,这使得注册信号处理程序变得棘手.例如,如果应用程序本身使用信号怎么办?我不想踩任何脚趾.我可能会考虑巧妙地使用它sigaction(2)来应对......但是还没有充分考虑这种可能性.
  3. atexit(3):显然没用,因为它在异常终止期间没有被调用(例如通过信号).
  4. preemptive unlink(2):这是非常好的,除了我需要文件在文件系统中保持可见(否则系统更难监控/故障排除).

你会在这做什么?

进一步说明

我在原帖中省略了一个细节,我现在意识到应该包含这个细节.在这种情况下,"文件"不是严格意义上的普通文件,而是POSIX消息队列.我通过创建它mq_open().它可以通过mq_close()或关闭close()(前者是我系统中后者的别名).它可以通过系统删除mq_unlink().所有这些使它类似于常规文件,除了我不能选择文件所在的目录.这使得当前最流行的答案(放置文件/tmp)变得不可行,因为"文件"是由系统在容量非常有限的虚拟文件系统中创建的.(我已经/dev/mqueue按照示例安装了虚拟文件系统man mq_overview).

这也解释了为什么我需要保持名称的名称(使立即取消链接方法不可行):"文件"必须在两个或多个进程之间共享.

c c++ file termination unlink

20
推荐指数
2
解决办法
5063
查看次数

CMake:如何最好地构建多个(可选)子项目?

想象一下包含几个组件的整体项目:

  • 基本
  • IO
  • 卷筒纸
  • 应用-A
  • 应用-B
  • 应用-C

现在,假设web依赖于依赖于basic的io,所有这些东西都在一个repo中并且有一个CMakeLists.txt来构建它们作为共享库.

我应该如何设置以便构建三个应用程序,如果每个应用程序都是可选的,并且可能在构建时不存在?

一个想法是在主仓库中有一个空的"apps"目录,我们可以克隆我们想要的任何应用程序回购.我们的主要CMakeLists.txt文件可以使用GLOB查找所有应用程序目录并构建它们(事先不知道将有多少个).这种方法的问题包括:

  • 显然,当你说时make,CMake不会重新发送,所以如果你添加一个新的应用程序,你必须cmake再次运行.
  • 它对进行构建的人施加了特定的结构.
  • 如何制作单个应用程序的两个克隆并将它们分别针对相同的库构建进行构建并不明显.

一般概念就像传统的递归CMake项目,但是较低级别的模块不一定事先知道哪些更高级别的模块将使用它们.但是,我不想要求用户在固定位置安装较低级别的库(例如/usr/local/lib).但是,我确实希望单个调用make来注意整个项目中已更改的依赖项,因此,如果我正在构建应用程序但已更改其中一个低级库,则所有内容都将重新编译.

modularity build cmake

20
推荐指数
2
解决办法
9311
查看次数