小编Ale*_*op.的帖子

C和C++中几乎完全相同的代码之间的执行时间差异很大(x9)

我试图从www.spoj.com解决这个练习:FCTRL - Factorial

你真的不必阅读它,只要你好奇就去做:)

首先我用C++实现它(这是我的解决方案):

#include <iostream>
using namespace std;

int main() {
    unsigned int num_of_inputs;
    unsigned int fact_num;
    unsigned int num_of_trailing_zeros;

    std::ios_base::sync_with_stdio(false); // turn off synchronization with the C library’s stdio buffers (from https://stackoverflow.com/a/22225421/5218277)

    cin >> num_of_inputs;

    while (num_of_inputs--)
    {
        cin >> fact_num;

        num_of_trailing_zeros = 0;

        for (unsigned int fives = 5; fives <= fact_num; fives *= 5)
            num_of_trailing_zeros += fact_num/fives;

        cout << num_of_trailing_zeros << "\n";
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我上传它作为g ++ 5.1的解决方案

结果是: …

c c++ performance gcc iostream

85
推荐指数
3
解决办法
6168
查看次数

带有符号和无符号操作数的'&'

我遇到了一个有趣的场景,根据正确的操作数类型我得到了不同的结果,我无法理解它的原因.

这是最小的代码:

#include <iostream>
#include <cstdint>

int main()
{
    uint16_t check = 0x8123U;

    uint64_t new_check = (check & 0xFFFF) << 16;

    std::cout << std::hex << new_check << std::endl;

    new_check = (check & 0xFFFFU) << 16;

    std::cout << std::hex << new_check << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在Linux 64bit上使用g ++(gcc版本4.5.2)编译了这段代码:g ++ -std = c ++ 0x -Wall example.cpp -o example

输出是:

ffffffff81230000

81230000

我无法真正理解第一种情况下输出的原因.

为什么在某些时候将任何时间计算结果提升为带符号的64位值(int64_t),从而导致符号扩展?

如果16位值在第一位左移16位然后提升到64位值,我会在两种情况下都接受'0'的结果.如果编译器首先提升checkto uint64_t然后执行其他操作,我也接受第二个输出.

但是如何&使用0xFFFF(int32_t)和0xFFFFU(uint32_t)会导致这两个不同的输出?

c++ bitwise-and c++11 sign-extension type-promotion

28
推荐指数
3
解决办法
2297
查看次数

具有/不具有throw/noexcept功能的潜在C++编译器优化

假设以下课程:

class Example
{
public:
...
    Example& operator=(const Example& rhs);
...
private:
    other_type *m_content;
    size_t m_content_size;
}

Example& Example::operator=(const Example& rhs)
{
    if (this != &rhs)
    {
        delete m_content;
        m_content = nullptr;
        m_content = getCopiedContent(rhs);
    }

    return *this;
}
Run Code Online (Sandbox Code Playgroud)

我知道这不是最好的实现方式,operator=但这是有目的的,因为我的问题是关于这两行:

    m_content = nullptr;
    m_content = getCopiedContent(rhs);
Run Code Online (Sandbox Code Playgroud)

可以编译器优化,m_content = nullptr;即使getCopiedContent未定义为throw()noexcept:

other_type* getCopiedContent(const Example& obj);
Run Code Online (Sandbox Code Playgroud)

一方面,编译器可以假设如果在m_content = nullptr;m_content用返回值覆盖值之后getCopiedContent,它可以优化整个m_content = nullptr;表达式.另一方面,如果编译器将其优化并 …

c++ exception throw compiler-optimization

9
推荐指数
1
解决办法
312
查看次数

std :: atomic可以用减量取消增量吗?

使用宽松的存储顺序,例如对于引用计数指针,是否允许编译器优化掉后续的递增和递减?

std::atomic_int32_t ai;
for (size_t i = 0; i < 10000; i++)
{
    ai.fetch_add(1, std::memory_order_relaxed);
    ai.fetch_sub(1, std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)

看看反汇编它看起来不像.但是由于允许重新排序并且atomic行为类似于计数器,只是线程安全,人们可以争辩说他可以优化,好像它是一个普通的int.

c++ multithreading atomic compiler-optimization c++11

8
推荐指数
1
解决办法
192
查看次数

除以零不会导致Nvidia Jetson出现运行时异常

我对ARM处理器的内部细节不是很熟悉,但是我不了解Nvidia Jetson Nano开发板上的以下行为。

C代码示例...

//main.c

#include <stdio.h>

int main()
{
  int fred = 123;
  int i;

  for(i = -10 ; i <= 10 ; i++)
    printf("%d / %d == %d\n", fred, i, fred / i);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译:

gcc main.c -ggdb
Run Code Online (Sandbox Code Playgroud)

运行生成的a.out可执行文件将产生以下输出...

123 / -10 == -12
123 / -9 == -13
123 / -8 == -15
123 / -7 == -17
123 / -6 == -20
123 / -5 == -24
123 / -4 == -30
123 / …
Run Code Online (Sandbox Code Playgroud)

c arm integer-division divide-by-zero armv8

8
推荐指数
1
解决办法
113
查看次数

运算符优先级和复杂表达式的评估顺序

我在看下面的代码:

#include <stdint.h>

void foo(uint32_t *pVal)
{
  uint32_t i = 8;

  *pVal = i *= 10;
}
Run Code Online (Sandbox Code Playgroud)

乍一看很明显,在返回之前foo(),*pVal将是80以及价值i.这确实是根据godbolt.org发生的事情:

foo:                                    # @foo
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     dword ptr [rbp - 12], 8
        imul    eax, dword ptr [rbp - 12], 10
        mov     dword ptr [rbp - 12], eax
        mov     rdi, qword ptr [rbp - 8]
        mov     dword ptr [rdi], eax
        pop     rbp
        ret
Run Code Online (Sandbox Code Playgroud)

但是从这里 …

c operator-precedence

5
推荐指数
0
解决办法
70
查看次数

为什么 x86-64 C/C++ 编译器没有为此代码生成更高效的汇编?

考虑以下局部变量的声明:

bool a{false};
bool b{false};
bool c{false};
bool d{false};
bool e{false};
bool f{false};
bool g{false};
bool h{false};
Run Code Online (Sandbox Code Playgroud)

在 x86-64 架构中,我希望优化器将这些变量的初始化减少到类似mov qword ptr [rsp], 0. 但相反,我使用所有编译器(无论优化级别如何)得到的结果是某种形式的:

mov     byte ptr [rsp + 7], 0
mov     byte ptr [rsp + 6], 0
mov     byte ptr [rsp + 5], 0
mov     byte ptr [rsp + 4], 0
mov     byte ptr [rsp + 3], 0
mov     byte ptr [rsp + 2], 0
mov     byte ptr [rsp + 1], 0
mov     byte …
Run Code Online (Sandbox Code Playgroud)

c++ performance initialization x86-64

5
推荐指数
1
解决办法
113
查看次数

在编译时验证宏参数的大小

假设我有一个宏(更多细节为何,以下是在PS部分)

void my_macro_impl(uint32_t arg0, uint32_t arg1, uint32_t arg2);

...

#define MY_MACRO(arg0, arg1, arg2)       my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2))
Run Code Online (Sandbox Code Playgroud)

将要在其上使用该宏的硬件是小尾数法,并使用32位体系结构,以便所有指针的宽度最大为(包括)32位宽度。我的目标是在用户通过uint64_tint64_t错误输入参数时警告用户。

我想使用sizeof这样的

#define MY_MACRO(arg0, arg1, arg2)       do \
                                         {  \
                                             static_assert(sizeof(arg0) <= sizeof(uint32_t));  \
                                             static_assert(sizeof(arg1) <= sizeof(uint32_t));  \
                                             static_assert(sizeof(arg2) <= sizeof(uint32_t));  \
                                             my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2));  \
                                         } while (0)
Run Code Online (Sandbox Code Playgroud)

但是用户可以使用MY_MACRO位域,然后我的代码无法编译:

错误:“ sizeof”对位字段的无效应用

问题:是否可以选择在编译时检测宏参数的大小是否大于(例如)uint32_t


聚苯乙烯

它的MY_MACRO作用类似于printf实时嵌入式环境。该环境有一个硬件记录器,最多可以接收5个参数,每个参数应为32位。目的是保留的标准格式printf。格式字符串是脱机解析的,并且解析器很清楚每个参数都是32位,因此它将根据%...格式字符串中的进行强制转换。可能的用法如下。

不需要的用法:

uint64_t time = systime_get();
MY_MACRO_2("Starting execution at …
Run Code Online (Sandbox Code Playgroud)

c sizeof bit-fields c11

4
推荐指数
1
解决办法
179
查看次数

uint64_t的安全低32位屏蔽

假设以下代码:

uint64_t g_global_var;

....
....

void foo(void)
{
    uint64_t local_32bit_low = g_global_var & 0xFFFFFFFF;
    ....
}
Run Code Online (Sandbox Code Playgroud)

使用当前的工具链,此代码可以按预期工作,local_32bit_low实际上包含的低32位g_global_var

我想知道标准C是否保证该代码将始终按预期工作?我担心的是,编译器可能会将0xFFFFFFFF视为-1的整数,并且提升为uint64_t0xFFFFFFFFFFFFFFFF时。

聚苯乙烯

我知道,为了安全起见,在这种情况下最好使用0xFFFFFFFFULL。关键是我在旧版代码中看到了它,我想知道是否值得修复。

c 64-bit bit-manipulation bitmask implicit-conversion

3
推荐指数
1
解决办法
116
查看次数

在使用对齐冲突进行强制转换后,指针算术是否仍然定义良好?

我知道,一旦取消引用,带有对齐冲突的指针转换的结果就会调用未定义的行为。

\n

但是仅用于地址计算(不取消引用)的指针转换怎么样?

\n
void *addr_calc(single_byte_aligned_struct_t *ptr, uint32_t dword_offset)\n{\n    uint32_t *dw_ptr = (uint32_t *)ptr;\n\n    return dw_ptr + dword_offset;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我们假设 的ptr值为X。能保证一定addr_calc()会回来X + sizeof(uint32_t) * dword_offset吗?

\n

我的假设是,但最近我在 C11 标准的J.2 节中看到了以下未定义行为

\n
\n

\xe2\x80\x94 两个指针类型之间的转换会产生不正确对齐的结果 (6.3.2.3)。

\n
\n

如果我理解正确的话,转换本身会调用未定义的行为,而不仅仅是取消引用,这意味着在这种情况下,即使是指针算术也可能表现出不可预测的行为。我对吗?

\n

c memory-alignment pointer-arithmetic undefined-behavior c11

3
推荐指数
1
解决办法
378
查看次数