小编Nem*_*emo的帖子

高效的无符号签名转换,避免实现定义的行为

我想定义一个带有unsigned intas参数的函数,并向参数返回一个int全等模UINT_MAX + 1.

第一次尝试可能如下所示:

int unsigned_to_signed(unsigned n)
{
    return static_cast<int>(n);
}
Run Code Online (Sandbox Code Playgroud)

但正如任何语言律师所知,从无符号转换为大于INT_MAX的已签名值是实现定义的.

我想实现这一点,以便(a)它只依赖于规范规定的行为; (b)它在任何现代机器上编译成无操作并优化编译器.

对于奇怪的机器......如果没有签名的int congruent将UINT_MAX + 1模数为unsigned int,那么假设我想抛出一个异常.如果有多个(我不确定这是否可能),那么就说我想要最大的一个.

好的,第二次尝试:

int unsigned_to_signed(unsigned n)
{
    int int_n = static_cast<int>(n);

    if (n == static_cast<unsigned>(int_n))
        return int_n;

    // else do something long and complicated
}
Run Code Online (Sandbox Code Playgroud)

当我不是一个典型的二元补充系统时,我并不太关心效率,因为我认为不太可能.如果我的代码成为2050年无所不在的符号量级系统的瓶颈,那么,我敢打赌,有人可以解决这个问题并对其进行优化.

现在,第二次尝试非常接近我想要的.尽管转换int为某些输入的实现定义,但是unsigned标准保证转换为保留模UINT_MAX + 1的值.所以条件确实检查我想要什么,它将在我可能遇到的任何系统上编译成什么.

但是......我仍然在int没有首先检查它是否会调用实现定义的行为.在2050年的一些假设系统中,它可以做谁知道什么.所以我想说我想避免这种情况.

问题:我的"第三次尝试"应该是什么样的?

回顾一下,我想:

  • 从unsigned int转换为signed int
  • 保留值mod UINT_MAX + 1
  • 仅调用标准强制行为
  • 在具有优化编译器的典型二进制补码机器上编译成无操作

[更新]

让我举一个例子来说明为什么这不是一个微不足道的问题.

考虑具有以下属性的假设C++实现:

  • sizeof(int) 等于4
  • sizeof(unsigned) 等于4
  • INT_MAX 等于32767
  • INT_MIN等于-2 …

c++ integer casting integer-overflow language-lawyer

83
推荐指数
3
解决办法
4万
查看次数

通过将同一个库链接两次来解决循环依赖关系?

我们将代码库分解为静态库.不幸的是,这些库具有循环依赖性; 例如,libfoo.a取决于,libbar.a反之亦然.

我知道处理这个的"正确"方法是使用链接器--start-group--end-group选项,如下所示:

g++ -o myApp -Wl,--start-group -lfoo -lbar -Wl,--end-group
Run Code Online (Sandbox Code Playgroud)

但在我们现有的Makefile中,问题通常是这样处理的:

g++ -o myApp -lfoo -lbar -lfoo
Run Code Online (Sandbox Code Playgroud)

(想象一下,这扩展到约20个具有复杂相互依赖性的库.)

我一直在通过我们的Makefiles将第二种形式更改为第一种形式,但现在我的同事们问我为什么......除了"因为它更清洁"以及另一种形式存在风险的模糊感,我不这样做有一个很好的答案.

因此,可以连接同一个库多次曾经创造出了问题?例如,如果同一个.o被拉入两次,链接是否会失败?或者是否有任何风险,我们可以结束相同的静态对象的两个副本,创建微妙的错误?

基本上,我想知道链接时间或运行时失败是否有可能多次链接同一个库; 如果是的话,如何触发它们.谢谢.

c++ linux linker circular-dependency ld

33
推荐指数
2
解决办法
1万
查看次数

std :: lock()是不明确的,不可实现的还是无用的?

(注意:使用std :: lock(c ++ 11)大量CPU负载进行评论时,大部分内容都是多余的,但我认为这个主题应该得到自己的问题和答案.)

我最近遇到了一些示例C++ 11代码:

std::unique_lock<std::mutex> lock1(from_acct.mutex, std::defer_lock);
std::unique_lock<std::mutex> lock2(to_acct.mutex, std::defer_lock);
std::lock(lock1, lock2); // avoid deadlock
transfer_money(from_acct, to_acct, amount);
Run Code Online (Sandbox Code Playgroud)

哇,我想,std::lock听起来很有趣.我想知道它的标准是什么意思?

C++ 11第30.4.3节[thread.lock.algorithm],第(4)和(5)段:

模板空锁(L1&,L2&,L3&...);

4 要求:每个模板参数类型应满足可锁定要求,[注意:unique_lock类模板在适当实例化时满足这些要求. - 结束说明]

5种效果:所有参数通过调用的顺序被锁定lock(), try_lock()unlock()在每个参数.调用序列不应导致死锁,否则不会被指定.[注意:必须使用诸如try-and-back-off之类的死锁避免算法,但未指定特定算法以避免过度约束实现.- 结束注释]如果调用lock()try_lock()抛出异常,unlock()则应调用已被lock()或调用锁定的任何参数try_lock().

请考虑以下示例.称之为"示例1":

Thread 1                    Thread 2
std::lock(lock1, lock2);    std::lock(lock2, lock1);
Run Code Online (Sandbox Code Playgroud)

这可能是僵局吗?

对标准的简单解读说"不".大!也许编译器可以为我订购我的锁,这将是一种整洁.

现在尝试例2:

Thread 1                                  Thread 2
std::lock(lock1, lock2, lock3, lock4);    std::lock(lock3, lock4); …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading language-lawyer c++11

28
推荐指数
2
解决办法
5459
查看次数

numeric_limits <int> :: is_modulo在逻辑上是矛盾的吗?

另一个问题,主题std::numeric_limits<int>::is_modulo出现了.但我想的越多,看起来规格或GCC或两者都有问题.

让我先从一些代码开始:

#include <limits>
#include <iostream>

bool test(int x)
{
    return x+1 > x;
}

int main(int argc, char *argv[])
{
    int big = std::numeric_limits<int>::max();

    std::cout << std::numeric_limits<int>::is_modulo << " ";
    std::cout << big+1 << " ";
    std::cout << test(big) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

当我用g++ -O3 -std=c++11(x86_64 GCC 4.7.2)编译它时,它产生以下输出:

1 -2147483648 1
Run Code Online (Sandbox Code Playgroud)

也就是说,is_modulo是的,一个加号INT_MAX是负数,一个加号INT_MAX大于INT_MAX.

如果你是那种有实际机会回答这个问题的人,你已经知道这里发生了什么.C++规范说整数溢出是Undefined Behavior; 允许编译器假设你不这样做; 因此争论x+1不可能INT_MAX; 因此编译器可能(并将会)编译test函数以true无条件地返回.到现在为止还挺好.

但是, …

c++ language-lawyer c++11

26
推荐指数
1
解决办法
584
查看次数

重新考虑浮点比较

这个主题在StackOverflow上出现了很多次,但我相信这是一个新的看法.是的,我已经阅读了布鲁斯道森的文章每个计算机科学家应该知道的关于浮点算术的内容这个很好的答案.

据我了解,在一个典型的系统上,比较浮点数是否相等有四个基本问题:

  1. 浮点计算不准确
  2. 无论a-b是"小"取决于规模ab
  3. 是否a-b为"小"取决于类型ab(例如浮动,双,长双)
  4. 浮点通常具有+ -infinity,NaN和非规范化表示,其中任何一个都可能干扰天真的公式

这个答案 - 又名."Google方法" - 似乎很受欢迎.它确实处理了所有棘手的案件.并且它确实非常精确地缩放比较,检查两个值是否在彼此的固定数量的ULP内.因此,例如,非常大的数字将"几乎相等"与无穷大相比较.

然而:

  • 在我看来,它非常混乱.
  • 它不是特别便携,严重依赖于内部表示,使用union来从float中读取位等.
  • 它只处理单精度和双精度IEEE 754(特别是没有x86长双)

我想要类似的东西,但使用标准的C++并处理长双打.如果可能的话,我指的是C++ 03,如果需要,我指的是C++ 11.

这是我的尝试.

#include <cmath>
#include <limits>
#include <algorithm>

namespace {
// Local version of frexp() that handles infinities specially.
template<typename T>
T my_frexp(const T num, int *exp)
{
    typedef std::numeric_limits<T> limits;

    // Treat +-infinity as +-(2^max_exponent).
    if (std::abs(num) > limits::max())
    {
        *exp …
Run Code Online (Sandbox Code Playgroud)

c++ floating-point ieee-754 language-lawyer

26
推荐指数
1
解决办法
3690
查看次数

protobuf-net序列化对象图

如果我有对象A和B都包含一些字段序列化字段F,并且都指向相同的可序列化对象C. protobuf-net是通过引用序列化还是按值序列化?当反序列化对象图时,protobuf-net是否会为AF和BF生成2个单独的对象?我问,因为我想知道序列化是否保留了引用相等性.

protocol-buffers protobuf-net

17
推荐指数
1
解决办法
3027
查看次数

如何实现"_mm_storeu_epi64"没有别名问题?

(注意:虽然这个问题是关于"存储"的,但"加载"情况具有相同的问题并且是完全对称的.)

SSE内在函数提供_mm_storeu_pd具有以下签名的函数:

void _mm_storeu_pd (double *p, __m128d a);
Run Code Online (Sandbox Code Playgroud)

所以,如果我有两个双精度矢量,并且我想将它存储到两个双精度数组中,我可以使用这个内在函数.

但是,我的矢量不是两个双打; 它是两个64位整数,我想将它存储到两个64位整数的数组中.也就是说,我想要一个具有以下签名的函数:

void _mm_storeu_epi64 (int64_t *p, __m128i a);
Run Code Online (Sandbox Code Playgroud)

但内在函数没有提供这样的功能.他们最接近的是_mm_storeu_si128:

void _mm_storeu_si128 (__m128i *p, __m128i a);
Run Code Online (Sandbox Code Playgroud)

问题是这个函数需要一个指针__m128i,而我的数组是一个数组int64_t.通过错误类型的指针写入对象违反了严格的别名,并且肯定是未定义的行为.我担心我的编译器现在或将来会重新排序或以其他方式优化存储,从而以奇怪的方式破坏我的程序.

要清楚,我想要的是一个我可以这样调用的函数:

__m128i v = _mm_set_epi64x(2,1);
int64_t ra[2];
_mm_storeu_epi64(&ra[0], v); // does not exist, so I want to implement it
Run Code Online (Sandbox Code Playgroud)

以下是创建此类功能的六次尝试.

尝试#1

void _mm_storeu_epi64(int64_t *p, __m128i a) {
    _mm_storeu_si128(reinterpret_cast<__m128i *>(p), a);
}
Run Code Online (Sandbox Code Playgroud)

这似乎有我担心的严格别名问题.

尝试#2

void _mm_storeu_epi64(int64_t *p, __m128i a) {
    _mm_storeu_si128(static_cast<__m128i *>(static_cast<void *>(p)), a);
}
Run Code Online (Sandbox Code Playgroud)

一般来说可能更好 …

c++ sse strict-aliasing intrinsics

17
推荐指数
1
解决办法
1506
查看次数

具有虚拟析构函数的池分配器

我正在开发一个旧的C++ 03代码库.一节看起来像这样:

#include <cstddef>

struct Pool
{ char buf[256]; };

struct A
{ virtual ~A() { } };

struct B : A
{
  static void *operator new(std::size_t s, Pool &p) { return &p.buf[0]; }
  static void operator delete(void *m, Pool &p) { } // Line D1
  static void operator delete(void *m) { delete m; } // Line D2
};

Pool p;

B *doit() { return new(p) B; }
Run Code Online (Sandbox Code Playgroud)

也就是说,B派生自A,但B的实例是从内存池中分配的.

(请注意,此示例稍微过于简单......实际上,池分配器执行的操作非常重要,因此operator delete需要在第D1行放置.)

最近,我们在更多编译器上启用了更多警告,而D2行引出了以下警告:

警告:删除'void*'未定义[-Wdelete-incomplete]

嗯,是的,很明显.但由于这些对象总是从池中分配,我认为不需要自定义(非放置)operator delete.所以我尝试删除D2线.但这导致编译失败:

new.cc:在析构函数'virtual …

c++ language-lawyer

16
推荐指数
1
解决办法
647
查看次数

为什么FLT_MAX和FLT_MIN不是正的和负的无穷大,它们的用途是什么?

从逻辑上讲,给定浮点值的性质,a的最大和最小可表示值float分别为正和负无穷大.

那么,为什么FLT_MAXFLT_MIN不是他们呢?我知道这是"标准要求的方式".但是,它们可以或者具有什么用途,因为它们目前位于可表示的数值范围的中间FLT_MAXFLT_MINfloat?其他数字限制具有一些实用性,因为它们保证了比较(例如"无INT可以测试大于INT_MAX").没有这种保证,这些浮动限制有什么用?

C++的一个激励范例:

#include <vector>
#include <limits>

template<typename T>
T find_min(const std::vector<T> &vec)
{
    T result = std::numeric_limits<T>::max();
    for (std::vector<T>::const_iterator p = vec.start() ; p != vec.end() ; ++p)
        if (*p < result) result = *p;
    return result;
}
Run Code Online (Sandbox Code Playgroud)

如果T是整数类型,则此代码可以正常工作,但如果它是浮点类型则不行.这很烦人.(是的,标准库提供min_element,但这不是重点.重点是模式.)

c c++

15
推荐指数
4
解决办法
3万
查看次数

加速地面集中所有对之间的L1距离

我有一个描述地面集的矩阵NxM(通常是10k X 10k元素).每行代表一个对象,每列代表一个特定的特征.例如,在矩阵中

   f1 f2 f3
x1 0  4  -1
x2 1  0  5
x3 4  0  0
x4 0  1  0
Run Code Online (Sandbox Code Playgroud)

对象x1在特征1中具有值0,在特征1中具有值4,在特征-1中具有值0.这个值是一般实数(double's).

我必须计算所有对象(所有对线)之间的几个自定义距离/不相似度.为了比较,我想计算L1(曼哈顿)和L2(欧几里德)距离.

我使用Eigen库来执行我的大部分计算.为了计算L2(欧几里得),我使用以下观察:对于两个大小为n的向量ab,我们有:

||a - b||^2 = (a_1 - b_1)^2 + (a_2 - b_2)^2 + ... +(a_n - b_n)^2
            = a_1^2 + b_1^2 - 2 a_1 b_1 + a_2^2 + b_2^2 - 2 a_2 b_2 + ... + a_n^2 + b_n^2 - 2 a_n b_n
            = a . a + b . …

c++ algorithm parallel-processing matrix eigen

14
推荐指数
1
解决办法
1035
查看次数