标签: language-lawyer

C/C++ 标准中定义的具有灵活数组成员的结构体的用法在哪里?

如果我有这样的代码

struct s { int x; char b[]; };

int main() {
    struct s s[10];
}
Run Code Online (Sandbox Code Playgroud)

我用“gcc -O2 -W -Wall -pedantic”进行编译,然后我得到:

<source>:4:14: warning: invalid use of structure with flexible array member [-Wpedantic]
    4 |     struct s s[10];
      |              ^
Run Code Online (Sandbox Code Playgroud)

gcc 是完全正确的。具有灵活数组成员的结构不能这样工作。

C/C++ 标准中的什么地方定义了这个?

c c++ language-lawyer

0
推荐指数
1
解决办法
80
查看次数

动态分配的结构是否已正确初始化?

对于POD结构,能否保证动态分配的结构在C++11及之后的版本中new Demo_Class[CONST_NUMBER]()得到很好的初始化(即不是垃圾)?

如果有人阐明有关初始化 POD 结构数组的详细规则,我们将不胜感激。

有一些关于基本类型的帖子,比如说new int{}等等。但是没有关于 POD 结构的直接答案。

更重要的是,大多数帖子根本没有提到 C++11 及之后的版本。

更新:感谢 eerorika 的快速回答。根据上述答案,[强调我的]:

对 T 类型的对象进行值初始化意味着:

否则,该对象将被零初始化

怎样才能充分理解呢?struct\class 可能有许多不同类型的成员变量。这是否意味着每个成员变量都将是零初始化的对象?例如:

struct Point
{
    int x;inty;
}; 

struct Demo
{
    Point pt; 
    double* ptr; 
    std::string str;
};.
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++11 c++17

0
推荐指数
1
解决办法
91
查看次数

为什么编译器创建一个只使用一次的变量?

考虑以下两个示例,两个示例均使用g++ (GCC) 12.1.0targeting x86_64-pc-linux-gnu:进行编译g++ -O3 -std=gnu++20 main.cpp

示例1:

#include <iostream>

class Foo {
public:
    Foo(){ std::cout << "Foo constructor" << std::endl;}
    Foo(Foo&& f) { std::cout << "Foo move constructor" << std::endl;}
    Foo(const Foo& f) {std::cout << "Foo copy constructor" << std::endl;}

    ~Foo() { std::cout << "Foo destructor" << std::endl;}
};

class Baz {
private:
    Foo foo;
public:
    Baz(Foo foo) : foo(std::move(foo)) {}
    ~Baz() { std::cout << "Baz destructor" << std::endl;}
};

Foo bar() {
    return …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer

0
推荐指数
1
解决办法
152
查看次数

通过将 NULL 转换为结构指针来确定结构成员的偏移量

考虑以下代码:

#include <inttypes.h>

struct test {
    int a;
    long b;
};

int main(void){
    intptr_t ptr = (intptr_t) &(((struct test *)NULL)->b);
    printf("%"PRIiPTR"\n", ptr); //prints 8
    //...
}
Run Code Online (Sandbox Code Playgroud)

我已经使用这种结构很长一段时间来确定结构成员的偏移量,但现在质疑这种结构是否从标准的角度得到了明确的定义。

我不清楚的是为什么在NULL稍后获取地址的指针上执行间接寻址是合法的?

c struct pointers language-lawyer

0
推荐指数
1
解决办法
71
查看次数

是否存在从函数指针到函数的隐式转换?

我写这篇文章主要是为了澄清我在 Stackoverflow 上偶然发现的一些关于函数指针的令人困惑/误导的信息。

让我们从一个例子开始:

#include <iostream>

void func ()
{
    std::cout<<"func here"<<'\n';
}

int main()
{
    void (*fp)()=func;
    void (&fref)()=func;

    func();//call through function
    (&func)();//call through function pointer
    (*fp)();//call through function
    fp();//call through function pointer
    fref();//call through function
    (&fref)();//call through function pointer
}
Run Code Online (Sandbox Code Playgroud)

这打印:

func here
func here
func here
func here
func here
func here
Run Code Online (Sandbox Code Playgroud)

可以看出,由于函数到函数指针的衰减cppreference,大多数时候可以使用函数来代替函数指针。

函数类型 T 的左值可以隐式转换为指向该函数的纯右值指针。这不适用于非静态成员函数,因为不存在引用非静态成员函数的左值。

但除此之外,函数指针看起来也可以用来代替函数,因为我可以使用它来调用函数而无需显式取消引用。

此外,这个 Stackoverflow 答案

另请注意,您不需要使用一元 * 来通过函数指针进行调用;两者 (*p1_foo)(); 和 (p1_foo)(); 由于函数到函数指针的转换,具有相同的结果。

以及这个 Stackoverflow 的答案

还有一个双重的便利:调用位置的函数指针会自动转换为函数值,因此您不必编写 * 来通过函数指针进行调用。

让它看起来好像存在一个隐式函数指针来进行函数转换。

c++ pointers function language-lawyer

0
推荐指数
1
解决办法
324
查看次数

如何使“this”指针常量表达式?

这是我之前的问题的后续问题:为什么成员函数返回非静态数据成员而不是核心常量表达式?

该问题中提到的示例的简化版本是:

struct S {
    const bool x = true;
    constexpr bool f() { return x; }
};

int main() {
  S s{};
  static_assert(s.f()); // error: 's' is not a constexpr;
}
Run Code Online (Sandbox Code Playgroud)

标准中适用的措辞是 N4861:[expr.const]/(5.1)

表达式E是核心常量表达式E,除非 的计算遵循抽象机 ([intro.execution]) 的规则,将计算以下其中一项:

  • (5.1) ([expr.prim.this]),但作为 的一部分进行求值的函数 ([dcl.constexpr])this除外;constexprE

据我可以解析,表达式E是并且s.f()它的计算结果是返回一个非静态成员。但这属于“例外”部分:成员函数是 constexpr 函数,它作为. 如果我解析正确,我期望得到常量表达式并且断言成功。thiss.f()this->xs.S::f()s.f()s.f()

s但是,该项目符号并未指定必须是常量表达式的要求。我不明白为什么声明sasconstexpr会编译程序,即使没有在此项目符号中定义的s要求constexpr

我只是在我的示例中应用了措辞(5.1),但我看不到 …

c++ this language-lawyer constant-expression

0
推荐指数
1
解决办法
304
查看次数

整个结构上是否允许使用 GCC 属性(打包)?

从一开始我就相信 __attribute__((packed)) 可以放在结构体或 typedef 上,如下所示:

typedef struct __attribute__((packed)) {
    uint8_t   m1;
    uint16_t  m2;
    uint8_t   m3;
    uint32_t  m4;
    uint8_t   m5;
} junk;

Run Code Online (Sandbox Code Playgroud)

但后来有人指出,最近的 gcc 手册中没有记录这种明显的用法,因为已经有几个版本了。相反,它说(在v.12中):“[packed] 属性不适用于非成员对象。”
整个结构不是成员对象,对吗?
那么上面的例子合法吗,还是依赖于UB(稍后可以咬)?

c gcc language-lawyer

0
推荐指数
1
解决办法
162
查看次数

由于 malloc 的结果似乎不能保证与任何内容对齐,它是否可用?

我最近了解到,取消引用未与某个对象 ( ) 对齐的指针uint32_t* foo = (uint32_t*)7; *foo = 5;实际上是未定义的行为:

C11 第 6.2.8 节:对象对齐:

完整的对象类型具有对齐要求,这对可以分配该类型的对象的地址施加了限制。对齐是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。对象类型对该类型的每个对象施加对齐要求:可以使用_Alignas关键字请求更严格的对齐。

好的,非常有趣。但malloc似乎根本不关心对齐:

7.22.3.4malloc函数

概要

#include <stdlib.h>
void *malloc(size_t size);

描述

malloc函数为大小由 size 指定且值不确定的对象分配空间。

退货

malloc函数返回空指针或指向已分配空间的指针。

因此:执行以下操作是否不太可能会引发未定义的行为?

uint32_t* a = malloc(10*sizeof(uint32_t));
*a = 7;
Run Code Online (Sandbox Code Playgroud)

毕竟,我们无法保证 的返回值与malloc任何内容对齐。

c malloc alignment language-lawyer

0
推荐指数
1
解决办法
93
查看次数

使用“易失性 uint8_t”代替“易失性 sig_atomic_t”是否合法?

以下代码使用 avolatile uint8_t而不是 avolatile sig_atomic_t作为 C 标准要求,因为在 avr 平台上该类型sig_atomic_t不可用。

这仍然是合法的代码吗?使用合法吗__SIG_ATOMIC_TYPE__

是否需要包含cli()/sei()宏?

#include <stdint.h>
#include <signal.h>
#include <avr/interrupt.h>

volatile uint8_t flag;  
//volatile sig_atomic_t flag; // not available in avr-gcc
//volatile __SIG_ATOMIC_TYPE__ flag; // ok?

void isr() __asm__("__vector_5") __attribute__ ((__signal__, __used__, __externally_visible__)); 
void isr() {
    flag = 1;
}

void func(void) {
  for (uint8_t i=0; i<20; i++) {
      flag = !flag;
  }
}
Run Code Online (Sandbox Code Playgroud)

c embedded avr interrupt-handling language-lawyer

0
推荐指数
1
解决办法
304
查看次数

类模板适用于 gcc 和 msvc,但不适用于 clang

我通过 Stanley 的《C++ Primer》一书了解了 C++ 中的类模板。然后我编写了以下程序,令人惊讶的是,它可以使用 gcc 编译,但不能使用 clang 编译。我不知道为什么会这样。也就是说,C++20 中哪个编译器是正确的。我还阅读了有关未定义行为的信息,但我不确定该程序是否具有该行为。

template <typename T>
struct test
{
    T y;
};  

int main()
{
    test t{1};   //compiles with gcc and msvc but not with clang!  
}
Run Code Online (Sandbox Code Playgroud)

那么有人可以告诉我根据 C++20 标准什么是正确的行为吗?

演示

c++ aggregate language-lawyer c++20

0
推荐指数
1
解决办法
74
查看次数