#include <limits.h>
int main(){
int a = UINT_MAX;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我这个 UB 或实现定义?
链接说它的 UB
https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Integer-Overflow-Basics
链接说它的实现定义
转换规则说:
否则,新类型是有符号的,值不能在其中表示;要么结果是实现定义的,要么引发实现定义的信号。
我们不是将 a 转换max unsigned value为 asigned value吗?
我所看到的方式,gcc 只是截断了结果。
struct test{
char c_arr[1];
};
test array[1] = {{1}};
test get(int index){
return array[index];
}
int main(){
char* a = get(0).c_arr;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译它g++没有警告但clang++打印以下内容:
warning: temporary whose address is used as value of local variable 'a' will be destroyed at the end of the full-expression
Run Code Online (Sandbox Code Playgroud)
这不正确吗?不get(0).c_arr返回指向全局数组的指针?
还是get(0)返回一个临时变量并且编译器错误地认为c_arr它只是它的一个实例,而不是全局变量?
为什么将此临时变量传递给函数可以在没有警告的情况下工作?
void call(char* in){}
int main(){
call(get(0).c_arr);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 假设这两个 cpp 文件:
#include <iostream>
class test{
public:
int num = 5;
};
int main(){
test t;
return t.num;
}
Run Code Online (Sandbox Code Playgroud)
class test{
public:
int num = 6; // <-- note this has a different value.
};
Run Code Online (Sandbox Code Playgroud)
我们用g++ 0.cc 1.cc.
从 C++11 开始,在类中初始化成员变量是有效的。我的问题是它如何编译 whiteout 链接器错误?这是未定义的行为吗?因为我们正在打破一个定义规则。如果没有使用类,这将在编译时产生链接错误。
我知道在一个类中定义一个函数会使其内联,因此可以在不同的文件中包含多个函数,但不确定多个变量如何?
void test(int& in);
void test(const int& in){
}
int main(){
int a = 5;
test(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面没有编译链接错误:undefined reference to `test(int&)'。
我对此有3个问题:
1- 为什么我们会收到链接错误?是因为添加const到定义中使其成为完全不同的功能吗?为什么在不使用引用时它会起作用,即这可以正常工作:
void test(int in);
void test(const int in){}
..
int a = 5;
test(a);
..
Run Code Online (Sandbox Code Playgroud)
2- 是否const进入函数声明、定义或两者?如果使用引用,行为似乎有所不同。
3-const参数上的关键字是否说“传递给我的参数应该是调用者中的常量”或“此参数在此函数范围内被视为常量,无论它在调用者中是否为常量”。我确定是后者,但想确认一下。
union test{
char a; // 1 byte
int b; // 4 bytes
};
int main(){
test t;
t.a = 5;
return t.b;
}
Run Code Online (Sandbox Code Playgroud)
这个链接说:https : //en.cppreference.com/w/cpp/language/union
从最近未写入的联合成员中读取是未定义的行为。
据此,我上面的示例代码有UB吗?如果是这样,那么联盟的意义何在?我认为重点在于从相同的内存位置读取/写入不同的值类型。
如果我需要访问该most recently written值,那么我将只使用常规变量而不是联合。
#include <iostream>
template <class T>
void call_1(T& in){
printf("%d\n", sizeof(in)); // 12
}
template <int N>
void call_2(int (&in)[N]){
printf("%d\n", sizeof(in)); // 12
}
int main(){
int a[] = {1,2,3};
call_1(a);
call_2(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据上面的代码片段,我有几个问题:
1-是call_1与call_2都有效的方式来传递通过引用整个阵列?
2- 为什么T&需要在call_1. 如果&省略,则传递指向数组第一个元素的指针。为什么不T&传递对数组第一个元素的引用,而是引用整个数组?
3-为什么我不能写template <T N>在call_2一个避免硬编码int?这不是有效的语法吗?
让我们检查Add并Multiply作为例子。哪一种可以归类为加宽?
假设输入是2 的补码中的有符号字符(即长度为 8 位),除非另有声明。
1+2 = 3
Run Code Online (Sandbox Code Playgroud)
这个操作似乎没有扩大。1、2 和 3 都适合一个字符。
但是,250 + 6溢出无符号字符。那么这是在扩大吗?
同样可以用有符号类型完成,将有符号125 + 5字符溢出到符号位中。这是在扩大吗?
-2-3 = -5
Run Code Online (Sandbox Code Playgroud)
这会使二进制字符溢出 1 位:
1 1 1 1 1 1 1 0
+ 1 1 1 1 1 1 0 1
------------------
1 1 1 1 1 1 0 1 1
Run Code Online (Sandbox Code Playgroud)
溢出通常会被丢弃,但是,这是否被视为扩大操作?
1 * 2 = 2
Run Code Online (Sandbox Code Playgroud)
即使结果仍然适合原始数据类型,所有乘法是否都在扩大?
上面的例子2仍然适合一个 8 位字符,但是,如果我用二进制手工进行数学运算,额外的0s会附加到结果的左侧,结果被丢弃。 …
assembly cpu-architecture twos-complement integer-arithmetic
#include <stdio.h>
struct test{
int a;
};
struct test get(int in);
int main(){
struct test t = get(1234);
printf("%d\n",t.a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
struct test{
char a; // Note this is char instead of int.
};
struct test get(int in){
struct test t = {in};
return t;
}
Run Code Online (Sandbox Code Playgroud)
struct test有两种不同的定义。一个 with int,另一个 withchar作为其数据类型。
这是未定义的行为吗?C 没有one dentition rule像 C++ 那样的官方语言,这篇文章说多个定义可以吗?不同的翻译单元是否可以定义同名的结构体?
#include <iostream>
class c1{
};
class c2{
};
int main(){
c1 a;
c2 b;
//b = static_cast<c2>(a); <-- will not compile
b = *reinterpret_cast<c2*>(&a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
b = static_cast<c2>(a); 不会编译出现此错误:
no matching conversion for static_cast from 'c1' to 'c2'
Run Code Online (Sandbox Code Playgroud)
使用reinterpret_cast和做 abit cast是实现这一目标的唯一方法吗?
int main(){
int64_t a = -1;
uint32_t b = -1;
bool c = a > b;
std:: cout << c << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的理解是b哪个较小的类型将转换为较大的类型a(unit32 到 int64):
然后a将有符号值转换为无符号值:
本质上我们的比较将变成:
18446744073709551615 > 4294967295
Run Code Online (Sandbox Code Playgroud)
但我的c结果是false。我在这里缺少什么?
int main() {
char a[5];
a[0] = 0;
return a[0];
}
Run Code Online (Sandbox Code Playgroud)
在这个片段中char a[5];,没有任何初始化的数组声明是否保证分配 5 个字节的连续内存?
或者因为稍后只有 1 个元素被初始化,编译器可以自由地使用该 1 个元素的寄存器?
我假设读取此数组旁边的任何其他索引0都是未定义的行为。
int main() {
char a[3] = {1,2,3};
return sizeof(a);
}
Run Code Online (Sandbox Code Playgroud)
为a保证在虚拟内存中连续字节?我知道它在物理内存中可能不是连续的,因为映射是由 MMU 在幕后完成的。
如果编译器注意到我没有获取任何元素的地址,那么是否可以将它们放在内存中的非连续地址上,甚至将它们放在寄存器中?
让我们假设优化器不会在我的示例中完全摆脱它。