小编Dar*_*bik的帖子

sizeof(T)== sizeof(const T)和alignof(T)== alignof(const T)

这似乎是合理的假设,T并且const T将两种类型的将是相同尺寸并具有相同的排列,但想一些实际的系统后,似乎他们可能是不同的.

让我解释:

假设您的系统有两种类型的内存:RAM和Flash(只读).RAM是8位可寻址的,而闪存只有16位可寻址.假设这是T:

struct T
{
  uint8_t x;
  uint16_t y;
};
Run Code Online (Sandbox Code Playgroud)

在字节可寻址RAM中,这个结构长度为3个字节....但是在双字节可寻址Flash(const变量所在的位置)中,由于对齐问题,这个结构必须至少有4个字节长.

所以这是我的问题:

c和c ++标准是否保证了大小和对齐const以及非const类型?

c c++ sizeof alignment

36
推荐指数
2
解决办法
1305
查看次数

结构由编译器重新排序

假设我有这样的结构:

struct MyStruct
{
  uint8_t var0;
  uint32_t var1;
  uint8_t var2;
  uint8_t var3;
  uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)

这可能会浪费很多(不是很多)空间.这是因为uint32_t变量的必要对齐.

实际上(在对齐结构以便它实际上可以使用uint32_t变量之后)它可能看起来像这样:

struct MyStruct
{
  uint8_t var0;
  uint8_t unused[3];  //3 bytes of wasted space
  uint32_t var1;
  uint8_t var2;
  uint8_t var3;
  uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)

更有效的结构将是:

struct MyStruct
{
  uint8_t var0;
  uint8_t var2;
  uint8_t var3;
  uint8_t var4;
  uint32_t var1;
};
Run Code Online (Sandbox Code Playgroud)

现在,问题是:

为什么编译器禁止(按标准)重新排序结构?

如果对结构进行重新排序,我认为你没有任何方法可以用脚射击自己.

c c++ struct memory-alignment

34
推荐指数
6
解决办法
5639
查看次数

定义新类型的内存

是否可以定义新类型的内存.例如,在某些嵌入式系统编译器中,您可以这样做:

__flash const char array[] = "This is memory in flash (not ram) so I can waste it!";
Run Code Online (Sandbox Code Playgroud)

因此可能更疯狂并定义一种新型存储器(比如说SD卡).

我基本上要问是否可以定义SD卡是什么(如何访问其中的数据)然后在sd内存中声明一个变量.(每当它看到一个写入它调用sd方法的地方,它看到一个读取它调用sd方法的地方):

class SDCard{
public:
  void write(void* data,size_t length);
  void* read(size_t length);
  void* memAlloc(size_t length);

};

__sd char myVar;  //Grabs an address in the sd card based on SDCard::memAlloc
myVar = 'A';  //Calls whatever I defined the sd card write operation as
char other = myVar;  //Calls whatever I defined the sd card read operation as
Run Code Online (Sandbox Code Playgroud)

我正在使用gcc如果我可以做一些特别的事情(我几乎愿意修改编译器源以允许我这样做).

这样的事情是可能的,但有一些问题:

struct Vol_t{   //Would represent …
Run Code Online (Sandbox Code Playgroud)

c++ memory gcc

23
推荐指数
1
解决办法
990
查看次数

C++易失性放置新

如何在易失性指针上执行放置新操作.

例如,我想做这样的事情:

volatile SomeStruct Object;
volatile SomeStruct* thing = &Object;
new (thing) SomeStruct(/*arguments to SomeStruct's constructor*/);
Run Code Online (Sandbox Code Playgroud)

我知道如果没有volatile关键字,这会有用......但是如何使用volatile变量呢?

注意:

Placement new定义如下:

void* operator new(size_t memoryRequested, void* pointer)
{
  return pointer;
}
Run Code Online (Sandbox Code Playgroud)

(顺便说一句,这是GCC如何实现它):

// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
Run Code Online (Sandbox Code Playgroud)

问题是我试图将thing类型转换volatile SomeStruct*void*,这是不允许的.

例如,如果我将new运算符更改为:

void* operator new(size_t memoryRequested, volatile void* pointer)
{
  return (void*)pointer;
} 
Run Code Online (Sandbox Code Playgroud)

它会编译,但会调用未定义的行为.

c++ volatile placement-new

17
推荐指数
2
解决办法
967
查看次数

编译器无法推断出返回类型?

我试图decltype在自动功能上使用关键字:

struct Thing {
   static auto foo() {
     return 12;
   }
   using type_t =
       decltype(foo());
};
Run Code Online (Sandbox Code Playgroud)

我得到以下错误(gcc 7.4):

<source>:6:25: error: use of 'static auto Thing::foo()' before deduction of 'auto'
            decltype(foo());
                         ^
<source>:6:25: error: use of 'static auto Thing::foo()' before deduction of 'auto'
Run Code Online (Sandbox Code Playgroud)

为什么编译器还没有推断出返回类型?

c++ decltype auto c++14

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

不断变化的价值观

假设我有一个结构定义:

struct thing
{
    thing* x;
    int z;

    thing() : x(this), z(0) {}
    void foo() const
    {
        this->x->z++;
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,我创建了一个指向自己的可变指针(邪恶的笑)

然后我可以像这样使用它:

int main()
{
    const thing c;
    c.foo();
    assert(c.z == 1);
    c.foo();
    assert(c.z == 2);
    return c.z;
}
Run Code Online (Sandbox Code Playgroud)

而且你可以看到我似乎可以改变一个恒定的值......这是UB吗?

c++ const undefined-behavior

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

std::function const 正确性

假设我有一个像这样的可调用类型:

struct mutable_callable
{
    int my_mutable = 0;
    int operator()() { // Not const
        return my_mutable++;
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,mutable_callable具有operator()修改成员变量的非常量.....

现在假设我创建了一个std::function我的类型:

std::function<int()> foo = mutable_callable{};
Run Code Online (Sandbox Code Playgroud)

现在我可以这样做:

void invoke(std::function<int()> const& z)
{
    z();
}

int main()
{
    invoke(foo); // foo changed.....oops
}
Run Code Online (Sandbox Code Playgroud)

现在据我所知std::functionsoperator()const按照:https : //en.cppreference.com/w/cpp/utility/functional/function/operator()

所以我的直觉是你不应该这样做......

但随后查看:https : //en.cppreference.com/w/cpp/utility/functional/function/function

这似乎没有对可调用类型是否具有常量施加任何限制operator()......

所以我的问题是这样的:我正确地假设这std::function<int()> const&本质上是一样的,std::function<int()>&因为两者的行为实际上没有区别......如果是这样,为什么不const正确?

c++ const-correctness std-function

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

易失性不按预期工作

考虑以下代码:

struct A{ 
  volatile int x;
  A() : x(12){
  }
};

A foo(){
  A ret;
  //Do stuff
  return ret;
}

int main()
{
  A a;
  a.x = 13;
  a = foo();
}
Run Code Online (Sandbox Code Playgroud)

使用g++ -std=c++14 -pedantic -O3我得到这个程序集:

foo():
        movl    $12, %eax
        ret
main:
        xorl    %eax, %eax
        ret
Run Code Online (Sandbox Code Playgroud)

根据我的估计,变量x应写入至少三次(可能是四次),但它甚至不写一次(函数foo甚至不被调用!)

更糟糕的是,当您向其添加inline关键字时,foo结果如下:

main:
        xorl    %eax, %eax
        ret
Run Code Online (Sandbox Code Playgroud)

我认为volatile意味着即使编译器看不到读/写的点,每次读或写都必须发生.

这里发生了什么?

更新:

A a;像这样把外部主要的声明:

A a;
int main()
{  
  a.x = 13;
  a …
Run Code Online (Sandbox Code Playgroud)

c++ g++ volatile language-lawyer

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

变量如何既可以是constexpr而不是constexpr?

我做了一个constexpr字符串类型,我打电话给StaticString.我从这个网站得到了这个想法.

我有一些奇怪的问题,编译器将变量视为constexpr一行,然后不是constexpr下一行.

这是代码:

constexpr StaticString hello = "hello";
constexpr StaticString hello2 = hello + " ";
constexpr StaticString world = "world";
constexpr StaticString both = hello + " world";
constexpr StaticString both2 = hello2 + world;
//This works fine (world is constexpr?)

//constexpr StaticString both3 = "hello " + world; 
//ERROR: "world" is not constexpr

int main(void)
{
    static_assert(hello[4] == 'o' ,"ERROR");
    static_assert(hello == "hello", "ERROR");
    static_assert(both2 == "hello world", …
Run Code Online (Sandbox Code Playgroud)

c++ compile-time-constant constexpr

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

放置新的虚假警告?

我有以下代码:

#include "type_traits"
#include <new>


void foo()
{
    std::aligned_storage<10,alignof(long)> storage;
    new (&storage) int(12);
}
Run Code Online (Sandbox Code Playgroud)

我有定义(与长度为10个字节)一些存储,并且我放置new荷兰国际集团的int到该位置

gcc 7.3给出以下警告:

<source>:10:10: warning: placement new constructing an object of type 'int' and size '4' in a region of type 'std::aligned_storage<10, 8>' and size '1' [-Wplacement-new=]
     new (&storage) int(12);
Run Code Online (Sandbox Code Playgroud)

如果我不正确,则此警告不正确.我在这里遗漏了什么或这个警告是虚假的吗?

c++ alignment placement-new

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