相关疑难解决方法(0)

如何正确地将unsigned char数组转换为uint32_t

所以,我正在尝试将unsigned chars 数组转换为a uint32_t,但每次都会得到不同的结果:

unsigned char buffer[] = {0x80, 0x00, 0x00, 0x00};;
uint32_t num = (uint32_t*)&buffer;
Run Code Online (Sandbox Code Playgroud)

现在,我一直收到这个警告:

警告:初始化从指针生成整数而不进行强制转换

当我改变num*numi 时,我没有得到那个警告,但这实际上并不是真正的问题(更新:嗯,现在我认为它们可能是相关的.),因为每次运行代码都有不同的结果.其次num,一旦它正确投射,应该是128,但是如果我需要改变缓冲区的字节顺序,我可以设法自己做,我想.

谢谢!

c casting

12
推荐指数
2
解决办法
3万
查看次数

std :: fabs()的优化不好?

最近我正在使用一个类似于以下代码的应用程序:

for (auto x = 0; x < width - 1 - left; ++x)
{
    // store / reset points
    temp = hPoint = 0;
    for(int channel = 0; channel < audioData.size(); channel++)
    {
        if (peakmode) /* fir rms of window size */
        {
            for (int z = 0; z < sizeFactor; z++)
            {
                temp += audioData[channel][x * sizeFactor + z + offset];
            }
            hPoint += temp / sizeFactor;
        }
        else /* highest sample in window */
        {
            for (int …
Run Code Online (Sandbox Code Playgroud)

c++ bit-manipulation

12
推荐指数
1
解决办法
1452
查看次数

如何避免别名并提高性能?

在此Stack Overflow答案中 ,证明了C++中的别名可能会降低代码速度.并且C++中的别名不仅适用于指针,它也适用于引用,更一般地适用于标准指定的这些类型.特别是有

一种聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员)

所以根据我的理解,如果我有如下代码,

 class A{
  public:
   int val;
 };

 void foo(vector<A> & array, int & size, A & a0) {
   for(int i=0;i<size;++i) {
    array[i].val = 2*a0.val;
   }
 }
Run Code Online (Sandbox Code Playgroud)

和可能的是,a0可以别名中的元素中的一个array,也可能是别名size由于上述引用的,所以a0size必须装载对于每次迭代导致性能下降.

  1. 然后我的问题是我应该怎么做代码以避免别名,并提高性能?
  2. 传递const &将无济于事,因为它不会避免标准规定的混叠.通过a0按值?但这会使a0我不喜欢的复制,因为在实践中,类A可能非常复杂,复制是一个非常昂贵的选择.
  3. 有没有一个通用的解决方案来避免C++中的别名?如果是,那是什么?

c++ c++11

12
推荐指数
1
解决办法
1615
查看次数

如何在C++中实现矢量调配?

struct vec2
{
    union
    {
        struct { float x, y; };
        struct { float r, g; };
        struct { float s, t; };
    };
    vec2() {}
    vec2(float a, float b) : x(a), y(b) {}
};
struct vec3
{
    union
    {
        struct { float x, y, z; };
        struct { float r, g, b; };
        struct { float s, t, p; };
        // Here is the problem with g++.
        struct { vec2 xy; float z; };
        struct { float x; vec2 …
Run Code Online (Sandbox Code Playgroud)

c++ mingw g++ glsl visual-studio

12
推荐指数
2
解决办法
683
查看次数

在MATLAB R2018a及更新版本中,无需数据复制即可将复杂转换为实数

MATLAB R2018a以来,复值矩阵在内部存储为单个数据块,每个矩阵元素的实部和虚部存储在彼此相邻的位置 - 它们称之为"交错复合体".(以前这样的矩阵有两个数据块,一个用于所有实际组件,一个用于所有虚构组件 - "单独复杂".)

我认为,由于存储现在允许它,因此应该可以将复值数组转换为具有两倍元素的实值数组,而无需复制数据.

MATLAB有一个函数typecast,它将数组转换为不同类型而不复制数据.例如,它可以用于将具有16个8位值的数组转换为具有2个双浮点数的数组.它在不复制数据的情况下执行此操作,将位模式重新解释为新类型.

遗憾的是,这个函数在复值数组上根本不起作用.

我想复制这段代码:

A = fftn(randn(40,60,20)); % some random complex-valued array
assert(~isreal(A))

sz = size(A);
B = reshape(A,1,[]);        % make into a vector
B = cat(1,real(B),imag(B)); % interleave real and imaginary values
B = reshape(B,[2,sz]);      % reshape back to original shape, with a new first dimension
assert(isreal(B))
Run Code Online (Sandbox Code Playgroud)

矩阵AB(在R2018a和更新版本中)完全相同的数据,完全相同的顺序.但是,为了达到目的,B我们必须将数据复制两次.

我尝试创建一个MEX文件来执行此操作,但我没有看到如何创建一个引用输入数组中的数据的新数组.这个MEX文件有效,但是在清除变量时会导致MATLAB崩溃,因为有两个数组引用相同的数据而没有意识到它们共享数据(即引用计数没有递增).

// Build with:
//    mex -R2018a typecast_complextoreal.cpp

#include <mex.h>

#if MX_HAS_INTERLEAVED_COMPLEX==0
#error "This MEX-file …
Run Code Online (Sandbox Code Playgroud)

arrays matlab types casting complex-numbers

12
推荐指数
1
解决办法
461
查看次数

使用reinterpret_cast的签名别名

采取以下代码

#include <iostream>

void func() {
    int i = 2147483640;
    while (i < i + 1)
    {
        std::cerr << i << '\n';
        ++i;
    }

    return;
}

int main() {
    func(); 
}
Run Code Online (Sandbox Code Playgroud)

这段代码显然是错误的,因为while循环仅在有符号的int i溢出(即UB)时才能终止,因此编译器可以例如将其优化为无限循环(Clang在上进行-O3)或执行其他类型的时髦操作。现在我的问题是:从我对C ++标准的阅读中,等同于签名的类型可能会别名(即指针int*unsigned*别名)。为了进行一些时髦的签名“包装”,以下内容是否具有未定义的行为?

#include <iostream>

static int safe_inc(int a)
{
    ++reinterpret_cast<unsigned&>(a);
    return a;
}

void func() {
    int i = 2147483640;
    while (i < safe_inc(i))
    {
        std::cerr << i << '\n';
        ++i;
    }

    return;
}

int main() {
    func(); …
Run Code Online (Sandbox Code Playgroud)

c++ signed memcpy language-lawyer reinterpret-cast

12
推荐指数
2
解决办法
262
查看次数

用memcpy"构造"一个​​可复制的对象

在C++中,这段代码是否正确?

#include <cstdlib>
#include <cstring>

struct T   // trivially copyable type
{
    int x, y;
};

int main()
{
    void *buf = std::malloc( sizeof(T) );
    if ( !buf ) return 0;

    T a{};
    std::memcpy(buf, &a, sizeof a);
    T *b = static_cast<T *>(buf);

    b->x = b->y;

    free(buf);
}
Run Code Online (Sandbox Code Playgroud)

换句话说,是*b一个生命已经开始的对象?(如果是的话,它什么时候开始呢?)

c++ lifetime language-lawyer

11
推荐指数
2
解决办法
1377
查看次数

最简单的经验法则是避免违反严格别名规则?

在阅读另一个关于别名的问题(什么是严格的别名规则?)及其最佳答案时,我意识到我仍然不完全满意,即使我认为我在那里理解了它.

(这个问题现在被标记为C和C++.如果您的答案仅涉及其中一个,请澄清哪个.)

所以我想了解如何在这个领域做一些开发,以积极的方式进行指针,但是使用一个简单的保守规则来确保我不引入UB.我在这里提出了这样的规则.

(更新:当然,我们可以避免所有类型的惩罚.但这不是很有教育意义.除非当然,除了例外之外,确实存在明确定义的union异常.)

更新2:我现在明白为什么这个问题中提出的方法不正确.但是,知道是否存在简单,安全的替代方案仍然很有趣.截至目前,至少有一个答案提出了这样的解决方案.

这是最初的例子:

int main()
{
   // Get a 32-bit buffer from the system
   uint32_t* buff = malloc(sizeof(Msg));

   // Alias that buffer through message
   Msg* msg = (Msg*)(buff);

   // Send a bunch of messages    
   for (int i =0; i < 10; ++i)
   {
      msg->a = i;
      msg->b = i+1;
      SendWord(buff[0] );
      SendWord(buff[1] );   
   }
}
Run Code Online (Sandbox Code Playgroud)

重要的是:

Msg* msg = (Msg*)(buff);
Run Code Online (Sandbox Code Playgroud)

这意味着现在有两个指针(不同类型)指向相同的数据.我的理解是,任何通过其中一个写入的尝试都会使另一个指针基本上无效.('无效'是指我们可以安全地忽略它,但通过无效指针读取/写入是UB.)

Msg* msg = (Msg*)(buff);
msg->a = …
Run Code Online (Sandbox Code Playgroud)

c c++ strict-aliasing

11
推荐指数
2
解决办法
633
查看次数

std :: array是否可以为更大数组的片段添加别名?

假设我们有一个指针,T* ptr;并且ptr, ptr+1, … ptr+(n-1)所有引用类型为T的有效对象.

是否有可能像STL一样访问它们array?或者执行以下代码:

std::array<T,n>* ay = (std::array<T,n>*) ptr
Run Code Online (Sandbox Code Playgroud)

调用未定义的行为?

c++ arrays strict-aliasing type-punning c++11

11
推荐指数
1
解决办法
347
查看次数

将double*转换为double(*)[N]

void compute(int rows, int columns, double *data) {
    double (*data2D)[columns] = (double (*)[columns]) data;
    // do something with data2D
}

int main(void) {
    double data[25] = {0};
    compute(5, 5, data);
}
Run Code Online (Sandbox Code Playgroud)

有时,将参数视为多维数组非常方便,但需要将其声明为指向平面数组的指针.将指针视为多维数组是否安全,compute如上例所示?我很确定内存布局可以保证正常工作,但我不知道标准是否允许指针以这种方式进行转换.

这会破坏任何严格的别名规则吗?指针算法的规则怎么样; 由于数据"实际上不是"a double[5][5],我们是否允许执行指针算法和索引data2D,或者是否违反了指针算法不会偏离适当数组范围的要求?是data2D即使保证指向正确的地方,还是它只是保证我们可以将它转换回并恢复data?标准报价将非常感激.

c arrays casting

10
推荐指数
1
解决办法
248
查看次数