小编cur*_*guy的帖子

char*和std :: uint8_t之间的reinterpret_cast* - 安全吗?

现在我们有时必须使用二进制数据.在C++中,我们使用字节序列,因为开头char是我们的构建块.定义为sizeof1,它是字节.char默认情况下,所有库I/O函数都使用.一切都很好,但总是有一点担心,有点奇怪,一些人的错误 - 一个字节中的位数是实现定义的.

所以在C99中,决定引入几个typedef让开发人员轻松表达自己的固定宽度整数类型.当然可选,因为我们从不想伤害便携性.其中uint8_t,迁移到C++ 11中std::uint8_t,固定宽度的8位无符号整数类型,对于真正想要使用8位字节的人来说是完美的选择.

因此,开发人员接受了新工具并开始构建库,这些库明确表示它们接受8位字节序列std::uint8_t*,std::vector<std::uint8_t>或者其他方式.

但是,或许经过深思熟虑,标准化委员会决定不要求实施,std::char_traits<std::uint8_t>因此禁止开发人员轻松,便携地实例化,比如说,std::basic_fstream<std::uint8_t>并轻松读取std::uint8_t二进制数据.或许,我们中的一些人不关心字节中的位数并且对它感到满意.

但遗憾的是,两个世界相互冲突,有时您必须将数据作为char*并将其传递给期望的库std::uint8_t*.但是等等,你说,是不是char变量位并std::uint8_t固定为8?它会导致数据丢失吗?

嗯,这里有一个有趣的标准.的char定义为保持正好一个字节和字节是内存的最低可寻址的块,所以用比特宽度比的较小不能有一个类型char.接下来,它被定义为能够保存UTF-8代码单元.这给了我们最小--8位.所以现在我们有一个typedef,它要求是8位宽,并且是一个至少8位宽的类型.但有其他选择吗?是的,unsigned char.请记住,签名char是实现定义的.还有其他任何一种 谢天谢地,没有.所有其他整数类型都需要超出8位的范围.

最后,std::uint8_t是可选的,这意味着如果未定义使用此类型的库将无法编译.但如果它编译呢?我可以非常自信地说,这意味着我们在8位字节的平台上CHAR_BIT == 8.

一旦我们有这方面的知识,我们已经8位字节,这std::uint8_t是实现为char或者unsigned char,我们可以假设,我们可以做reinterpret_castchar*std::uint8_t*,反之亦然?它是便携式的吗?

这是我的Standardese阅读技巧让我失望的地方.我读了关于安全派生的指针([basic.stc.dynamic.safety]),据我所知,以下内容:

std::uint8_t* buffer = /* ... */ ;
char* buffer2 …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing language-lawyer c++11 uint8t

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

约束函数会允许模板参数取决于函数参数吗?

在C ++ 17中,此代码是非法的:

constexpr int foo(int i) {
    return std::integral_constant<int, i>::value;
}
Run Code Online (Sandbox Code Playgroud)

这是因为即使foo可以在编译时进行评估,编译器仍然需要产生指令以在运行时执行它,从而使模板实例化成为不可能。

在C ++ 20中,我们将具有consteval需要在编译时评估的函数,因此应删除运行时约束。这是否意味着该代码将是合法的?

consteval int foo(int i) {
    return std::integral_constant<int, i>::value;
}
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer class-template constexpr c++20

55
推荐指数
3
解决办法
1521
查看次数

C标准是否允许为指针分配任意值并递增它?

这段代码的行为是否定义得很好?

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    void *ptr = (char *)0x01;
    size_t val;

    ptr = (char *)ptr + 1;
    val = (size_t)(uintptr_t)ptr;

    printf("%zu\n", val);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的意思是,我们可以为指针分配一些固定数字,即使它指向某个随机地址也会增加它吗?(我知道你不能取消引用它)

c pointers pointer-arithmetic language-lawyer

52
推荐指数
4
解决办法
5292
查看次数

C++无法通过虚拟基础A从基础A转换为派生类型B.

我有三个班:

class A {};

class B : virtual public A {};
class C : virtual public A {};

class D: public B, public C {};
Run Code Online (Sandbox Code Playgroud)

尝试从A*到B*的静态强制转换我得到以下错误:

cannot convert from base A to derived type B via virtual base A
Run Code Online (Sandbox Code Playgroud)

c++ casting virtual-inheritance downcast static-cast

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

是否有可能通过指向另一个未释放子对象的指针来获得一个子对象的指针?

看下面这个简单的代码:

struct Point {
    int x;
    int y;
};

void something(int *);

int main() {
    Point p{1, 2};

    something(&p.x);

    return p.y;
}
Run Code Online (Sandbox Code Playgroud)

我希望main可以将返回值优化为return 2;,因为something它无法访问p.y,只能返回的指针p.x

但是,没有一个主要的编译器会优化mainto 的返回值2上帝保佑

如果仅允许访问,标准中是否存在可以something修改的内容?如果是,这是否取决于标准布局?p.yp.xPoint

如果我使用something(&p.y);,该return p.x;怎么办?

c++ pointers offsetof language-lawyer c++17

51
推荐指数
1
解决办法
1397
查看次数

指针算术与两个不同的缓冲区

请考虑以下代码:

int* p1 = new int[100];
int* p2 = new int[100];
const ptrdiff_t ptrDiff = p1 - p2;

int* p1_42 = &(p1[42]);
int* p2_42 = p1_42 + ptrDiff;
Run Code Online (Sandbox Code Playgroud)

现在,标准保证p2_42指向p2[42]哪个?如果没有,在Windows,Linux或webassembly堆上总是如此吗?

c++ pointers pointer-arithmetic language-lawyer

50
推荐指数
4
解决办法
2484
查看次数

替代虚拟机制实现?

C++支持通过虚拟机制进行动态绑定.但据我所知,虚拟机制是编译器的实现细节,标准只是指定了在特定场景下应该发生的行为.大多数编译器通过虚拟表和虚拟指针实现虚拟机制.是的,我知道这是如何工作的,所以我的问题不是关于虚拟指针和表的实现细节.我的问题是:

  1. 是否有任何编译器以虚拟指针和虚拟表机制以外的任何其他方式实现虚拟机制?据我所见,最多(阅读g ++,Microsoft visual studio)通过虚拟表,指针机制实现它.那么实际上还有其他任何编译器实现吗?
  2. sizeof只有一个虚函数的任何类的将是一个指针(vptr的内部尺寸this)上编译,所以考虑到虚拟PTR和TBL机制本身是编译器实现,将这个说法我在上面做永远是真的吗?

c++ virtual-functions vtable vptr

48
推荐指数
4
解决办法
4837
查看次数

使用C++中的私有函数覆盖公共虚函数

是否有任何理由使重写的C++虚函数的权限与基类不同?这样做有危险吗?

例如:

class base {
    public:
        virtual int foo(double) = 0;
}

class child : public base {
    private:
        virtual int foo(double);
}
Run Code Online (Sandbox Code Playgroud)

C++常见问题解答说,这是一个坏主意,但没有说为什么.

我已经在一些代码中看到了这个习惯用法,我相信作者试图让这个类最终,基于一个假设,即不可能覆盖私有成员函数.但是,本文显示了重写私有函数的示例.当然,C++ faq的另一部分建议不要这样做.

我的具体问题:

  1. 在派生类和基类中使用不同的虚拟方法权限是否存在任何技术问题?

  2. 有没有合理的理由这样做?

c++ overriding virtual-functions access-control

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

下面的第一个片段编译,但第二个片段不编译.为什么?

下面的代码片段编译(演示):

struct A{ int i = 10; };

int main() {
    struct A{ int i = 20; };
    struct A;
    struct A a;
}
Run Code Online (Sandbox Code Playgroud)

但这不是:

struct A{ int i = 10; };

int main() {
//    struct A{ int i = 20; };
    struct A;
    struct A a;
}
Run Code Online (Sandbox Code Playgroud)

我可以看到答案可能是标准中的这些段落:

[basic.lookup.elab]/2[basic.scope.pdecl]/7.

但我真的不知道如何从这两段中推断出上面显示的不同行为.

需要注意的是在第一个例子中,struct A不是第一次在声明阐述类型说明符 struct A;,但在定义struct Amain().

在第二个例子中,struct A先在声明阐述型说明符 struct …

c++ declaration definition language-lawyer name-lookup

47
推荐指数
3
解决办法
4188
查看次数

为什么编译器没有合并多余的std :: atomic写入?

我想知道为什么没有编译器准备将相同值的连续写入合并到单个原子变量,例如:

#include <atomic>
std::atomic<int> y(0);
void f() {
  auto order = std::memory_order_relaxed;
  y.store(1, order);
  y.store(1, order);
  y.store(1, order);
}
Run Code Online (Sandbox Code Playgroud)

我尝试过的每个编译器都会发出三次上面的编写.什么合法的,无种族的观察者可以看到上述代码与具有单次写入的优化版本之间的差异(即,不是"假设"规则适用)?

如果变量是易变的,那么显然不适用优化.在我的情况下有什么阻止它?

这是编译器资源管理器中的代码.

c++ multithreading compiler-optimization c++11 stdatomic

47
推荐指数
5
解决办法
4494
查看次数