相关疑难解决方法(0)

什么时候可以做/使用具有未指定行为的东西?

在C++中,有些东西出现在明确定义和未定义之间.具体而言,这些被称为实现定义未指定.现在,我对未指明的东西很感兴趣.

什么时候可以使用这些功能,什么时候应该避免?是否有正确代码的未指定行为的良好示例?在编写软件时,它是否是最佳选择?

Matt McNabb提供的定义:

  • 未定义 - 任何事情都可能发生

  • 实现定义 - 有限数量的结果是可能的,编译器的文档必须说明会发生什么

  • 未指定 - 可能有限数量的结果 - 通常标准描述了可能结果的集合

  • 定义明确 - 以上都不是

  • 格式良好的程序 - 无错误编译的程序(可能表现出未定义的行为)

后续问题:

放松的原子是否被指定为未指定或明确定义?

标记为从不同角度谈论相同想法的问题的副本.标记为同样的问题涉及未指明行为的定义,而这里的问题是关于如何以及何时使用它.

c++ undefined-behavior unspecified-behavior relaxed-atomics

-2
推荐指数
1
解决办法
203
查看次数

为什么1ul << 64返回1而不是0?

考虑以下代码:

// Simply loop over until 64 is hit. 
unsigned long x = 0;
for (int i = 0; i <= 64; i++) {
  if (i == 64) {
    x = 1ul << i;
    printf("x: %d\n", x);
  }
}
Run Code Online (Sandbox Code Playgroud)

我们知道无符号长是64位宽,左移1到64位将变为1000 ... 000(后面有64个零),并且会被截断为0.但是,实际的打印输出给出:

x: 1
Run Code Online (Sandbox Code Playgroud)

奇怪的是,如果我们这样做的话

printf("x: %d\n", (1ul << 64));
Run Code Online (Sandbox Code Playgroud)

它会打印0.

任何人都可以解释为什么会这样吗?为什么在第一种情况下,程序错误地产生1而不是0,但在第二种情况下它是正确的?

c math unsigned gcc long-integer

-2
推荐指数
1
解决办法
1719
查看次数

具有无限多(未命名)参数的函数 - 如何正确访问这些参数?

我有一个棘手的问题,我今天一直在玩,但为此我还没有想出一个优雅的解决方案.

我们知道,表单的函数void func()需要无限多的参数.现在我已经整理了一个非常简单的最小工作代码片段:

#include <stdio.h>

int func()
{

    printf("%d, %d, %d, %d\n");
    return 0;
}

int func() {
    sucks(0 /* Offset */, 1, 2, 3, 4);
}
Run Code Online (Sandbox Code Playgroud)

好的,我们现在可以使用尽可能多的参数调用func().我正在试验的问题是:我们如何正确访问这些论点的内容?printf()函数打印出类似这样的东西......只是为了验证参数是否实际存在:

anonymous@melina:/tmp$ ./a.out 
1 2 3 4
Run Code Online (Sandbox Code Playgroud)

所以现在的问题是:上面的代码片段有点hackish.有没有正确的方法来访问这些参数?或者你是否真的要乱用堆栈指针和内联汇编?作为第一次尝试,我考虑将堆栈指针放在函数的开头,例如,

uint64_t sp;
asm( "mov %%rsp, %0" : "=rm" ( sp ));
Run Code Online (Sandbox Code Playgroud)

...并以某种方式使用它,猜测这些参数实际上在哪里(在内存中).但是......到目前为止我没有成功.

c

-2
推荐指数
1
解决办法
65
查看次数

未初始化的局部变量是静态的吗?

如果变量被初始化(i = 0),每次调用函数 func 时它仍然是 1,但是

当 i 未初始化时:

#include <stdio.h>

int funct(void);
int main(void)
{
    funct();
    funct();
    funct();

    return 0;
}

int funct(void)
{
    int i;  
    static int j = 0;

    i++;
    j++;

    printf(" i = %d         j = %d\n", i, j);
}
Run Code Online (Sandbox Code Playgroud)

输出是

 i = 1      j = 1
 i = 2      j = 2
 i = 3      j = 3
Run Code Online (Sandbox Code Playgroud)

我不明白为什么变量 i 的行为像静态变量!

c variables static

-2
推荐指数
1
解决办法
53
查看次数

如果在 C 中不检查 feof 会发生什么?

在读/写操作期间是否绝对有必要检查feof()

我问的原因是因为我有一个执行读/写一次的程序,下面是代码:

while (1) {

      data = read_file_data(file);
      write_file_data(data, filename);

      if (feof(file)) 
          print(read error)
}
Run Code Online (Sandbox Code Playgroud)

这只是伪代码,但是是否有必要检查feof()像这样一次读取的情况?目前,我认为只有当您在上面的阅读之后再阅读一遍时才有必要,如下所示:

while (1) {

      data = read_file_data(file);
      write_file_data(data, filename);

      if (feof(file))       // feof error occurred oops
          print(read error)

      data = read_file_data(file); // reading after error    
}
Run Code Online (Sandbox Code Playgroud)

EOF reached最后,即使发生错误(读过去) ,阅读会产生什么后果EOF

c file-io pointers file feof

-2
推荐指数
1
解决办法
251
查看次数

c ++析构函数在同一个对象上被调用了2次?

我有以下代码片段:

#include<iostream>
using namespace std;

class Test {

public:

    Test()  { cout << "Constructor is executed\n"; }
    ~Test() { cout << "Destructor is executed\n";}
    void show()  {  this->Test::~Test(); }
};

int main() {

    Test t;
    t.show();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

Constructor is executed
Destructor is executed
Destructor is executed
Run Code Online (Sandbox Code Playgroud)

问题:如果t.show()已经在"this"对象(即当前对象)上调用析构函数,导致"析构函数被执行"显示一次,那么是什么原因导致它第二次显示?在这种情况下哪个对象被破坏了?

c++ destructor c++11

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

在采访中询问指针算术输出

char s[] = "arista2015";
char *p = s;
printf("%s",p+p[4]-p[1]);
Run Code Online (Sandbox Code Playgroud)

该程序将输出作为

ista2015

有人可以解释输出吗?

c string

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

为什么catch没有处理这个错误C++

当我在linux机器上运行它时,我希望catch块能够捕获异常.而我得到了分段错误.为什么是这样 ?它不应该打印"抓住异常"

void handle_eptr(std::exception_ptr eptr) // passing by value is ok
{
    try {
        if (eptr) {
            std::rethrow_exception(eptr);
        }
    } catch(const std::exception& e) {
        std::cout << "Caught exception \"" << e.what() << "\"\n";
    }
}

int main()
{

    char *c =(char*) 0x10;



    std::exception_ptr eptr;
    try {
        std::string s = c;

    } catch(...) {
        std::cout<< "Caught exception";
        //eptr = std::current_exception(); // capture
    }
   // handle_eptr(eptr);
    std::cout << "Normal Exit";
}
Run Code Online (Sandbox Code Playgroud)

c++ exception

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

可以修改字符串文字和非字符串非复合文字吗?

字符串文字是左值,它打开门以修改字符串文字.

来自C in a Nutshell:

在C源代码中,文字是表示固定值的标记,可以是整数,浮点数,字符或字符串.文字的类型由其值和符号决定.这里讨论的文字不同于C99标准中引入的复合文字.复合文字是普通的可修改对象,类似于变量.

虽然 C不严格禁止修改字符串文字,但您不应尝试这样做.首先,编译器将字符串文字视为常量,可将其置于只读存储器中,在这种情况下,尝试的写操作会导致错误.另一方面,如果程序中使用了两个或多个相同的字符串文字,编译器可能会将它们存储在同一位置,因此当您访问另一个时,修改它会导致意外结果.

  1. 第一段说"C中的字面值表示固定值".

    • 这是否意味着不应修改文字(复合文字除外)?

    • 由于字符串文字不是复合文字,是否应修改字符串文字?

  2. 第二段说"编译器不会严格禁止修改字符串文字".那么字符串文字应该被修改吗?
  3. 这两段是否相互矛盾?我怎么理解他们?

  4. 可以修改既不是复合文字也不是字符串文字的文字?

c literals string-literals

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

我找到了一个用C编写的base64解码器。当我用GCC编译它时它工作正常。但是cl.exe出错了。为什么?

/**
 * Copyright (c) 2006-2018 Apple Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, …
Run Code Online (Sandbox Code Playgroud)

c gcc cl

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