相关疑难解决方法(0)

C宏创建一个掩码 - 可能吗?我找到了一个GCC错误吗?

我有点好奇创建一个宏来为设备寄存器生成位掩码,最高可达64位.这样就BIT_MASK(31)产生了0xffffffff.

但是,有几个C示例不能像我想的那样工作,而是我得到的0x7fffffff.这是因为编译器假设我想要签名输出,而不是无符号输出.所以我尝试了32,并注意到该值回绕到0.这是因为C标准声明如果移位值大于或等于要移位的操作数中的位数,则结果是未定义的.那讲得通.

但是,鉴于以下计划,bits2.c:

#include <stdio.h>

#define BIT_MASK(foo) ((unsigned int)(1 << foo) - 1)

int main()
{
    unsigned int foo;
    char *s = "32";

    foo = atoi(s);
    printf("%d %.8x\n", foo, BIT_MASK(foo));

    foo = 32;
    printf("%d %.8x\n", foo, BIT_MASK(foo));

    return (0);
}
Run Code Online (Sandbox Code Playgroud)


如果我编译gcc -O2 bits2.c -o bits2,并在Linux/x86_64机器上运行它,我得到以下内容:

32 00000000
32 ffffffff
Run Code Online (Sandbox Code Playgroud)


如果我使用相同的代码并在Linux/MIPS(big-endian)机器上编译它,我得到这个:

32 00000000
32 00000000
Run Code Online (Sandbox Code Playgroud)


在x86_64机器上,如果我使用gcc -O0 bits2.c -o bits2,那么我得到:

32 00000000
32 00000000
Run Code Online (Sandbox Code Playgroud)


如果我调整BIT_MASK到 …

c bit-manipulation

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

当我使用 int32_t 循环变量时,为什么我的 for 循环不会停止?

i在我的程序中,我发现当is时循环无法正确退出int32_t。看起来像是整数溢出,并且远大于10,并且循环不会停止。请告诉我发生了什么以及如何在大型项目中避免此错误。

#include <iostream>
#include <stdint.h>
int f(int n){

    for (int32_t i = 0; i < 10; ++i)
    {
        int64_t time = 4500000000 +  (i) * 500000000;
        std::cout << time<< " i: " << i << std::endl;

    }
    return 0;
}

int main ()
{
    return f(10);
}
Run Code Online (Sandbox Code Playgroud)

代码链接

c++

13
推荐指数
1
解决办法
1239
查看次数

重复移动"x << = 1"后,值是否会为0?

我想知道x在以下程序中是否会达到零.

请考虑:

int main ()
{
    int x = 1;
    while (x)
      {
        x <<= 1;
      }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该程序的预期行为是正常退出还是永远循环?

c bit-shift

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

g ++优化打破了循环

几天前,我遇到了我认为是g ++ 5.3中有关在更高-OX优化级别嵌套for循环的错误.(专门为它-O2而经历过-O3).问题是,如果你有两个嵌套的for循环,它有一些内部和来跟踪总迭代次数,一旦这个总和超过它的最大值,就会阻止外部循环终止.我能够复制的最小代码集是:

int main(){
    int sum = 0;
    //                 Value of 100 million. (2047483648 less than int32 max.)
    int maxInner = 100000000;

    int maxOuter = 30;

    // 100million * 30 = 3 billion. (Larger than int32 max)

    for(int i = 0; i < maxOuter; ++i)
    {
        for(int j = 0; j < maxInner; ++j)
        {
            ++sum;
        }
        std::cout<<"i = "<<i<<" sum = "<<sum<<std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

当使用g++ -o run.me main.cpp它编译时,它按预期输出运行:

i = …
Run Code Online (Sandbox Code Playgroud)

c++ optimization for-loop nested-loops

8
推荐指数
3
解决办法
1049
查看次数

为什么向上移位int会产生负数?

我是位操作技巧的新手,我写了一个简单的代码来查看在单个数字上进行单个位移的输出. 2

#include <iostream>
int main(int argc, char *argv[])
{

  int num=2;

 do
   {
     std::cout<<num<<std::endl;
     num=num<<1;//Left shift by 1 bit.

   } while (num!=0);


  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出如下.

2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
-2147483648
Run Code Online (Sandbox Code Playgroud)

显然,连续比特移位到左边由1个比特,将导致零,因为它已经在上面进行,但为什么计算机输出一个负数在最后终止在循环之前(自NUM接通零)??

然而,当我替换时int num=2,unsigned int num=2我获得相同的输出,除了最后一个数字是这个时间显示为正,2147483648而不是-2147483648

gcc在Ubuntu Linux上使用编译器

c c++ bit-manipulation bit-shift

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

C ++设计:从基类转换为派生类,没有额外的数据成员

我写了很多处理消息协议的代码。消息协议通常会具有通用的消息帧,可以从串行端口或套接字反序列化。该帧包含消息类型,并且必须根据消息类型来处理消息有效负载。

通常,我用访问器方法和构造函数编写一个多态类集,该构造函数引用消息框。

我想到的是,我可以直接从消息框架派生访问器类,然后从消息框架重新解释_cast到适当的访问器类,而不是基于对消息框架的引用来构造访问器类。这使代码更加简洁,并节省了一些字节和处理器周期。

请参见下面的示例(极度虚构和压缩)。显然,对于生产代码,所有这些都需要适当地封装,强制转换成为派生类的成员,更好地分离了所关注的问题,并添加了一些验证。为了简洁起见,已全部删除。

#include <iostream>
#include <cstring>
#include <vector>

struct GenericMessage
{
  GenericMessage(const char* body):body_(body, body+strlen(body)){}
  std::vector<char> body_;  
};

struct MessageType1:public GenericMessage
{
    int GetFoo()const
    {
        return body_[2];
    }
    int GetBar()const
    {
        return body_[3];
    }    
};

int main() 
{
    GenericMessage myGenericMessage("1234");
    MessageType1* myMgessageType1 = reinterpret_cast<MessageType1*>(&myGenericMessage);
    std::cout << "Foo:" << myMgessageType1->GetFoo() << std::endl;
    std::cout << "Bar:" << myMgessageType1->GetBar() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我从来没有见过任何地方这样做。考虑到派生没有其他数据成员,以这种方式从基础到派生有任何不利之处吗?

c++ inheritance

6
推荐指数
1
解决办法
1376
查看次数

这段代码中的第二个溢出在哪里

以下是GNU C参考手册第74页的代码:

如果您的代码使用带符号循环索引,请确保索引不会溢出,以及从索引派生的所有已签名表达式.这是一个有问题的代码的例子,有两个溢出实例.

for( i = INT_MAX - 10 ; i <= INT_MAX; i++)
    if( i+1 < 0 ) //first overflow
    {
        report_overflow();
        break; 
    }
Run Code Online (Sandbox Code Playgroud)

由于存在两个溢出,编译器可能会以与环绕假设不兼容的方式优化或转换两个比较.

c

6
推荐指数
1
解决办法
87
查看次数

为什么需要花费这么长时间才能完成100亿到10亿?

为什么这个循环(到10亿)只需要几个声音来执行...

for (i = 0; i < 1000000000; i++)
{

}
Run Code Online (Sandbox Code Playgroud)

...但这个循环(达到100亿)需要> 10分钟?

for (i = 0; i < 10000000000; i++)
{

}
Run Code Online (Sandbox Code Playgroud)

它不应该只需要30秒左右(3秒x 10)?

c loops for-loop

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

如何处理浮点下溢?

我正在尝试理解C++数值属性.因此,我对下溢现象感兴趣.任何人都可以给我一个下溢的例子以及如何处理它?

c++ floating-point underflow

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

C++编译器如何优化错误的分层向下转换以导致真正的未定义行为

请考虑以下示例:

class Base {
public:
    int data_;
};

class Derived : public Base {
public:
    void fun() { ::std::cout << "Hi, I'm " << this << ::std::endl; }
};

int main() {
    Base base;
    Derived *derived = static_cast<Derived*>(&base); // Undefined behavior!

    derived->fun(); 

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

根据C++标准,函数调用显然是未定义的行为.但是在所有可用的机器和编译器(VC2005/2008,RH Linux和SunOS上的gcc)上,它按预期工作(打印"嗨!").有谁知道配置此代码可以正常工作?或者可能是具有相同想法的更复杂的例子(注意,Derived不应该携带任何额外的数据)?

更新:

从标准5.2.9/8:

类型"指针CV1 B",其中B是一个类类型的右值,可以转换为类型"指针CV2 d",的右值,其中d是从乙派生的类(第10节),如果一个有效的标准从"指针d"转换到"指针到B"的存在(4.10),CV2是相同cvqualification为或者更大cvqualification比,CV1,和B不是虚拟基类d的空指针值(4.10)转换为目标类型的空指针值.如果类型是"指针CV1 B"点右值进行B实际上是类型d的对象的子对象,将所得指针指向类型D.的包围对象否则,铸造的结果是不确定的.

还有一个9.3.1(感谢@Agent_L):

如果为非X类型的对象或从X派生的类型调用类X的非静态成员函数,则行为未定义.

谢谢,迈克.

c++ compiler-optimization undefined-behavior

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