所以,我正在尝试将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,但是如果我需要改变缓冲区的字节顺序,我可以设法自己做,我想.
谢谢!
最近我正在使用一个类似于以下代码的应用程序:
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) 在此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由于上述引用的,所以a0和size必须装载对于每次迭代导致性能下降.
const &将无济于事,因为它不会避免标准规定的混叠.通过a0按值?但这会使a0我不喜欢的复制,因为在实践中,类A可能非常复杂,复制是一个非常昂贵的选择.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) 自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)
矩阵A和B(在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) 采取以下代码
#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++中,这段代码是否正确?
#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和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) 假设我们有一个指针,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)
调用未定义的行为?
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?标准报价将非常感激.