小编Sam*_*Lou的帖子

GCC可以警告我修改C99中const结构的字段吗?

我在尝试制作常量正确的代码时偶然发现了一个小问题.

我本来想写一个函数,它接受一个const结构的指针,告诉编译器"请告诉我,如果我正在修改结构,因为我真的不想".

我突然想到编译器会允许我这样做:

struct A
{
    char *ptrChar;
};

void f(const struct A *ptrA)
{
    ptrA->ptrChar[0] = 'A'; // NOT DESIRED!!
}
Run Code Online (Sandbox Code Playgroud)

这是可以理解的,因为实际上const是指针本身,而不是它指向的类型.我想让编译器告诉我,我正在做一些我不想做的事情,但是,如果可能的话.

我使用gcc作为我的编译器.虽然我知道上面的代码应该是合法的,但我仍然检查它是否会发出警告,但没有任何结果.我的命令行是:

gcc -std=c99 -Wall -Wextra -pedantic test.c
Run Code Online (Sandbox Code Playgroud)

有可能解决这个问题吗?

c const c99 compiler-warnings

37
推荐指数
4
解决办法
1603
查看次数

访问私有嵌套类

我做了这个简单的课程,仍然在玩我的想法:

class A {
private:
    class B {};

public:
    B getB() {
        return B();
    };
};
Run Code Online (Sandbox Code Playgroud)

从C++ 03开始,这个类编译得很好,但是没有很好的方法可以将结果分配给getB()左值,在这个意义上:

A::B b = A().getB();
Run Code Online (Sandbox Code Playgroud)

不编译.

我通过使用中间模板得到它,以这种方式:

template <typename T>
struct HideType {
    typedef T type;
};

HideType<A::B>::type b = A().getB();
Run Code Online (Sandbox Code Playgroud)

但这看起来很糟糕,因为这个简单的任务是得到一个A :: B左值变量.

从C++ 11开始就不再这样了,或者至少它不适用于gcc.此代码仍无效:

A::B b = A().getB();
Run Code Online (Sandbox Code Playgroud)

但这有效的:

auto b = A().getB();
Run Code Online (Sandbox Code Playgroud)

标准方面是否存在漏洞?

c++ language-lawyer c++11

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

在任何基于x86的体系结构中,是否有浮点密集型代码会产生位精确的结果?

我想知道在C或C ++中使用浮点运算的任何代码在任何基于x86的体系结构中是否都会产生精确的结果,而不管代码的复杂性如何。

据我所知,自从Intel 8087开始,任何x86架构都使用了准备处理IEEE-754浮点数的FPU单元,而且我看不出任何原因导致不同架构的结果不同。但是,如果它们不同(即由于不同的编译器或不同的优化级别),那么是否有某种方法可以通过仅配置编译器来产生位精确结果?

c x86 ieee-754 fast-math

5
推荐指数
1
解决办法
824
查看次数

当const引用绑定到临时引用时,堆栈中会发生什么?

C++标准允许将const引用绑定到rvalues,从而延长临时的生命周期,直到引用超出范围.但是,我无法弄清楚这是如何实际编译的,让我用一个例子来解释:

std::string foo() {
    return std::string("foo");
}

void bar() {
    VeryBigObject obj;
    // Perhaps do something with the big object
}

int main(int, char **) {
    const std::string &foo_str = foo();
    bar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

据我所知,使用x86架构作为例子,首先foo()调用函数并在堆栈中构造字符串对象,这意味着从rsp寄存器中减去所需的空间量(假设为64)位结构); 之后,rsp寄存器返回其原始值,释放函数foo()正在填充的堆栈空间,如果我理解正确,调用bar()将使用该堆栈空间来构造VeryBigObject,这将覆盖该字符串.

考虑到所有这些,在调用foo()汇编域后,如何延长字符串的生命周期?

c++ stack const-reference

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

有效的C++ 03模板代码无法在C++ 11中编译

在编写正常编译的有效C++ 03模板代码时,我遇到了一个小的(很容易解决的)问题,在使用C++ 11方言时无法编译.

问题出现在模板参数分辨率上.让这段代码成为一个例子:

template <uint32_t number>
struct number_of_bits {
    enum  {
        value = 1 + number_of_bits<number >> 1>::value
    };
};

template <>
struct number_of_bits<0> {
    enum  {
        value = 0
    };
};
Run Code Online (Sandbox Code Playgroud)

由于C++ 11现在允许">>"完成一个模板参数列表,该列表将模板化参数作为最后一个参数,因此在解析此代码时会产生问题.

我使用GCC(版本4.8.1)作为我的编译器,它使用命令行正常编译:

g++ test.cc -o test
Run Code Online (Sandbox Code Playgroud)

但是当我添加-std=c++11命令行开关时它无法编译:

g++ -std=c++11 test.cc -o test
Run Code Online (Sandbox Code Playgroud)

这是一个C++ 11语言功能还是GCC中的一个错误?这是一个已知的错误,如果是这样的话?

c++ template-meta-programming c++11

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

虚拟方法和vtable查找的最终说明符

我观察到当某个类的方法被标记为final在C++ 11中时,vtable中没有查找来调用该方法,即使是从指针调用,至少使用GCC生成的程序集.让这段代码作为例子:

class Base {
public:
    Base() : retval(0) {}
    virtual ~Base(){}
    virtual int method() {
        return retval;
    }
protected:
    uint32_t retval;
};

class DerivedFinal : public Base {
public:
    int method() final {
        return retval + 2;
    }
};

int main() {
    Base *bptr = new Base();
    DerivedFinal *df = static_cast<DerivedFinal *>(bptr);
    return df->method();
}
Run Code Online (Sandbox Code Playgroud)

请注意,代码使用这样的返回值来使汇编代码易于阅读.

主要的装配看起来像这样:

<+0>:     push   %rbp
<+1>:     mov    %rsp,%rbp
<+4>:     push   %rbx
<+5>:     sub    $0x18,%rsp
<+9>:     mov    $0x10,%edi
<+14>:    callq  0x400750 <_Znwm@plt>
<+19>: …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

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