在C++中,有些东西出现在明确定义和未定义之间.具体而言,这些被称为实现定义和未指定.现在,我对未指明的东西很感兴趣.
什么时候可以使用这些功能,什么时候应该避免?是否有正确代码的未指定行为的良好示例?在编写软件时,它是否是最佳选择?
Matt McNabb提供的定义:
未定义 - 任何事情都可能发生
实现定义 - 有限数量的结果是可能的,编译器的文档必须说明会发生什么
未指定 - 可能有限数量的结果 - 通常标准描述了可能结果的集合
定义明确 - 以上都不是
格式良好的程序 - 无错误编译的程序(可能表现出未定义的行为)
后续问题:
放松的原子是否被指定为未指定或明确定义?
考虑以下代码:
// 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,但在第二种情况下它是正确的?
我有一个棘手的问题,我今天一直在玩,但为此我还没有想出一个优雅的解决方案.
我们知道,表单的函数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)
...并以某种方式使用它,猜测这些参数实际上在哪里(在内存中).但是......到目前为止我没有成功.
如果变量被初始化(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 的行为像静态变量!
在读/写操作期间是否绝对有必要检查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?
我有以下代码片段:
#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"对象(即当前对象)上调用析构函数,导致"析构函数被执行"显示一次,那么是什么原因导致它第二次显示?在这种情况下哪个对象被破坏了?
char s[] = "arista2015";
char *p = s;
printf("%s",p+p[4]-p[1]);
Run Code Online (Sandbox Code Playgroud)
该程序将输出作为
ista2015
有人可以解释输出吗?
当我在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 in a Nutshell:
在C源代码中,文字是表示固定值的标记,可以是整数,浮点数,字符或字符串.文字的类型由其值和符号决定.这里讨论的文字不同于C99标准中引入的复合文字.复合文字是普通的可修改对象,类似于变量.
虽然 C不严格禁止修改字符串文字,但您不应尝试这样做.首先,编译器将字符串文字视为常量,可将其置于只读存储器中,在这种情况下,尝试的写操作会导致错误.另一方面,如果程序中使用了两个或多个相同的字符串文字,编译器可能会将它们存储在同一位置,因此当您访问另一个时,修改它会导致意外结果.
第一段说"C中的字面值表示固定值".
这是否意味着不应修改文字(复合文字除外)?
由于字符串文字不是复合文字,是否应修改字符串文字?
这两段是否相互矛盾?我怎么理解他们?
可以修改既不是复合文字也不是字符串文字的文字?
/**
* 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)