小编rsp*_*984的帖子

C++三元运算符执行条件

我不确定C/C++三元运算符的执行保证.
例如,如果给出一个地址和一个布尔值来告诉该地址是否适合阅读,我可以使用if/else轻松避免错误读取:

int foo(const bool addressGood, const int* ptr) {
    if (addressGood) { return ptr[0]; }
    else { return 0; }
}
Run Code Online (Sandbox Code Playgroud)

但是?:,ptr除非addressGood是真的,否则三元运算符()可以保证不会被访问?
或者优化编译器是否可以生成ptr在任何情况下访问的代码(可能使程序崩溃),将值存储在中间寄存器中并使用条件赋值来实现三元运算符?

int foo(const bool addressGood, const int* ptr) {
    // Not sure about ptr access conditions here.
    return (addressGood) ? ptr[0] : 0;
}
Run Code Online (Sandbox Code Playgroud)

谢谢.

c c++ memory pointers conditional-statements

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

C/C++严格别名,对象生命周期和现代编译器

我面临着关于C++严格别名规则及其可能含义的困惑.请考虑以下代码:

int main() {
  int32_t a = 5;
  float* f = (float*)(&a);
  *f = 1.0f;

  int32_t b = a;   // Probably not well-defined?
  float g = *f;    // What about this?
}
Run Code Online (Sandbox Code Playgroud)

看看C++规范,3.10.10节,从技术上讲,没有一个给定的代码似乎违反了给定的"别名规则":

如果程序试图通过以下类型之一以外的左值访问对象的存储值,则行为未定义:
...合格的访问者类型列表...

  • *f = 1.0f;不会违反规则,因为无法访问存储的值,即我只是通过指针写入内存.我不是从记忆中读书或试图在这里解释一个值.
  • 该行int32_t b = a;不违反规则,因为我通过其原始类型进行访问.
  • float g = *f;出于同样的原因,这条线并没有违反规则.

另一个线程中,成员CortAmmon实际上在响应中提出了相同的点,并且添加了通过写入活动对象而产生的任何可能的未定义行为,如 *f = 1.0f;将在标准的"对象生存期"定义(似乎是对于POD类型来说是微不足道的).

但是:互联网上有大量证据表明上述代码将在现代编译器上产生UB.例如,见这里这里.
在大多数情况下,论证是编译器可以自由考虑&a,f而不是相互混叠,因此可以自由重新安排指令.

现在最大的问题是,如果这种编译器行为实际上是对标准的"过度解释".
唯一一次标准谈论"混叠"的唯一一次是在3.10.10的脚注中,其中明确指出那些是控制混叠的规则.
正如我之前提到的,我没有看到任何上述代码违反了标准,但是很多人(可能还有编译人员)认为它是非法的.

我真的很感激这里的一些澄清.

小更新:
正如成员BenVoigt指出的那样,int32_t …

c++ memory compiler-construction strict-aliasing type-punning

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

不使用placement new返回的指针时C++严格别名

这可能会导致未定义的行为吗?

uint8_t storage[4];

// We assume storage is properly aligned here.
int32_t* intPtr = new((void*)storage) int32_t(4);

// I know this is ok:
int32_t value1 = *intPtr;
*intPtr = 5;

// But can one of the following cause UB?
int32_t value2 = reinterpret_cast<int32_t*>(storage)[0];
reinterpret_cast<int32_t*>(storage)[0] = 5;
Run Code Online (Sandbox Code Playgroud)

char有严格别名的特殊规则.如果我使用char而不是 uint8_t它仍然是未定义的行为?还有什么变化?

正如成员DeadMG指出的那样,reinterpret_cast依赖于实现.如果我改用C风格的演员(int32_t*)storage,会有什么变化?

c++ strict-aliasing placement-new language-lawyer type-punning

8
推荐指数
2
解决办法
735
查看次数

在哪里指定OpenGL ES 2.0如何在片段着色器中表示浮动纹理值?

我正在尝试使用OpenGL ES 2.0做一些GPGPU.
在我看来,GL_NV_draw_buffers和GL_OES_texture_float扩展是这里的一些基本要素.

这个问题与GL_OES_texture_float扩展有关:从桌面世界来看,如果格式是固定点(如GL_RGBA),我习惯在着色器中访问纹理时在[0..1]范围内.
咨询相应的OES扩展页面,它说:

"......如果纹理的内部格式是定点的,则组件被限制为[0..1].否则,不会修改值."

现在我已经多次在网上听到过(例如答案:OpenGL GLSL采样器总是返回从0.0到1.0的浮点数),ES 2.0也支持访问片段着色器中未展开的值.但是这个功能在哪里指定?扩展说"否则,值不会被修改",但由于OpenGL ES规范只知道定点格式,因此对我来说没有意义.

另外,据我所知,扩展只指定浮点值可以从客户端内存读取到纹理中,但不指定纹理在图形内存中的表示方式(即每个通道有多少位).这有什么官方规格吗?

最后,我想在我的片段着色器中将未展开的浮点值写入FBO颜色附件,最好每个通道使用32位.这可能吗?

graphics android gpgpu opengl-es opengl-es-2.0

7
推荐指数
0
解决办法
678
查看次数

C++中的共享内存缓冲区,不违反严格的别名规则

我正在努力实现共享内存缓冲区而不破坏C99的严格别名规则.

假设我有一些处理一些数据的代码,需要有一些'临时'内存来运行.我可以把它写成:

void foo(... some arguments here ...) {
  int* scratchMem = new int[1000];   // Allocate.
  // Do stuff...
  delete[] scratchMem;  // Free.
}
Run Code Online (Sandbox Code Playgroud)

然后我有另一个功能,做一些其他需要一个临时缓冲区的东西:

void bar(...arguments...) {
  float* scratchMem = new float[1000];   // Allocate.
  // Do other stuff...
  delete[] scratchMem;  // Free.
}
Run Code Online (Sandbox Code Playgroud)

问题是在操作期间可能会多次调用foo()和bar(),并且在性能和内存碎片方面,整个地方的堆分配可能非常糟糕.一个明显的解决方案是分配一个适当大小的公共共享内存缓冲区,然后将其作为参数传递给foo()和bar(),BYOB样式:

void foo(void* scratchMem);
void bar(void* scratchMem);

int main() {
  const int iAmBigEnough = 5000;
  int* scratchMem = new int[iAmBigEnough];

  foo(scratchMem);
  bar(scratchMem);

  delete[] scratchMem;
  return 0;
}

void foo(void* scratchMem) {
  int* smem = (int*)scratchMem;
  // …
Run Code Online (Sandbox Code Playgroud)

c++ memory buffer strict-aliasing type-punning

7
推荐指数
1
解决办法
1700
查看次数

如何正确使用glDiscardFramebufferEXT

此问题与OpenGL ES 2.0 Extension EXT_discard_framebuffer有关.

我不清楚哪些案例证明使用此扩展是合理的.如果我调用glDiscardFramebufferEXT()并将指定的可附加图像置于未定义状态,这意味着:
- 我不再关心内容,因为它已经与glReadPixels()一起使用了,
- 我不在乎因为它已经与glCopyTexSubImage()一起使用了,所以内容已经存在,
- 我不应该首先进行渲染.

显然,只有前两种情况有意义,还是其他情况下glDiscardFramebufferEXT()是有用的?如果是,这些情况是哪些?

iphone android gpgpu opengl-es opengl-es-2.0

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

在这种情况下,为什么c ++模板参数推断失败?

我正在尝试编写自己的委托系统作为boost :: functions的替代,因为后者执行了大量的堆分配,我认为这些分配是有问题的.
我已将此作为替换(简化,实际使用池内存和放置新的但这很简单,可以重现错误):

template<class A, class B>
struct DelegateFunctor : public MyFunctor {
  DelegateFunctor(void (*fptr)(A, B), A arg1, B arg2) : fp(fptr), a1(arg1), a2(arg2) {}

  virtual void operator()() { fp(a1, a2); }

  void (*fp)(A, B);  // Stores the function pointer.
  const A a1; const B a2;  // Stores the arguments.
};
Run Code Online (Sandbox Code Playgroud)

和这个辅助函数:

template<class A, class B>
MyFunctor* makeFunctor(void (*f)(A,B), A arg1, B arg2) {
  return new DelegateFunctor<A,B>(f, arg1, arg2);
}
Run Code Online (Sandbox Code Playgroud)

奇怪的事情发生在这里:

void bar1(int a, int b) {
  // do …
Run Code Online (Sandbox Code Playgroud)

c++ templates delegates boost function-pointers

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

如何在OpenGL ES 2.0着色器中处理NaN或inf

这基于以下问题:在OpenGL着色器中检测NaN的最佳方法

标准GLSL定义用于检测的isnan()和isinf()函数.OpenGL ES 2.0着色语言没有.我怎么能处理NaN和Infs呢?

iphone android gpgpu opengl-es opengl-es-2.0

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