int i = i;
int main() {
int a = a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
int a = a
肯定有未定义的行为 (UB),关于它的更多细节在
读取未初始化的值总是未定义的行为吗?或者有例外吗?.
但是呢int i = i
?在 C++ 中,我们可以为全局变量分配非常量值。i
在遇到声明之前声明并零初始化(因为它具有文件范围)。在这种情况下,我们将0
在定义的后面分配给它。可以说这没有 UB 吗?
#include <stdio.h>
int main() {
char a = 5;
char b[2] = "hi"; // No explicit room for `\0`.
char c = 6;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
每当我们编写一个用双引号括起来的字符串时,C 都会自动为我们创建一个字符数组,其中包含该字符串,并以 \0 字符结尾 http://www.eskimo.com/~scs/cclass/notes/sx8。 html
在上面的示例中,b
只有 2 个字符的空间,因此空终止字符没有位置可放置,但编译器正在重新组织内存存储指令,以便将a
和c
存储b
在内存中,以便为 a 腾出\0
空间数组的末尾。
这是预期的还是我遇到了未定义的行为?
int main(){\
int a = 5;\
return a;\
}
Run Code Online (Sandbox Code Playgroud)
以上编译正常。我假设 C 预处理器在编译之前删除了反斜杠?
int main(){
int a = 5;
return a;}
Run Code Online (Sandbox Code Playgroud)
似乎并非所有\n
(新行)字符都像使用宏一样被删除,它只是主要删除了反斜杠。
我已经在多行宏中看到过这种用法,例如:
#define TEST(in)\
int a = in; \
int b = 6;
int main(){
TEST(5)
return 0;
}
Run Code Online (Sandbox Code Playgroud)
int main(){
int a = 5; int b = 6;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
预处理将删除反斜杠以及\n
上面示例中的字符,但为什么它没有删除我第一个示例中的所有换行符?
int main(){
char a = -5;
char b = -6;
int c = a+b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在不同的体系结构中得到了不同的结果,使用gcc
.
对x86
变量c
进行了正确的符号扩展,我得到-11
.
在其他一些架构c
上没有符号扩展,你得到a+b
位转换为 an的结果,int
我得到501
.
这是未定义的行为吗?
在读取值时,未定义行为(UB) 的一个明显示例是:
int a;
printf("%d\n", a);
Run Code Online (Sandbox Code Playgroud)
下面的例子呢?
int i = i; // `i` is not initialized when we are reading it by assigning it to itself.
int x; x = x; // Is this the same as above?
int y; int z = y;
Run Code Online (Sandbox Code Playgroud)
上面的三个例子都是 UB,还是有例外?
#include <stdio.h>
int main(){
int *p = '\0';
if (p == NULL){
// this block will get executed.
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我已经读过0
,NULL
并且\0
都等于0
C 中的整数常量。那么上面的代码在设置和检查 NULL 指针时在技术上是否正确?我想它仍然需要避免,因为\0
它主要用于终止字符串并且它在这里的用法令人困惑?
typedef struct {
//
} list;
Run Code Online (Sandbox Code Playgroud)
对比
typedef struct list{
//
} list;
Run Code Online (Sandbox Code Playgroud)
我在另一篇文章中读到过(例如使用匿名结构与带有 typedef 的命名结构),其中说这两个几乎是等效的,并且需要后者的唯一时间是在引用结构本身时。
但是,以下内容可以用 clang 和 gcc 编译得很好:
#include <stdio.h>
typedef struct {
struct list *next;
} list;
int main(){
list l;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面我有一个匿名结构引用它自己。这是如何编译的?
class test{
public:
int call();
};
int test::call();
int main(){return 0;}
Run Code Online (Sandbox Code Playgroud)
上面的不会编译,出现这个错误:
error: declaration of 'int test::call()' outside of class is not definition
Run Code Online (Sandbox Code Playgroud)
但是,如果这样使用模板,则允许使用相同的代码:
class test{
public:
template<class T>
int call();
};
template int test::call<int>(); // what's the point of this line?
template <class T>
int test::call(){
T in = 5;
return in;
}
int main(){
test t;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
1-重新声明有什么意义?我在其他项目中看到过类似的代码。
2- 为什么它可以编译而我的第一个代码片段却不能?
关于 C 中类型转换的简单问题,假设这行代码:
signed char a = 133;
Run Code Online (Sandbox Code Playgroud)
由于有符号字符的最大值是128
,上面的代码是否具有implementation defined
根据第三条转换规则的行为?
如果值不能用新类型表示并且它不是无符号的,那么新类型是有符号的并且值不能在其中表示;要么结果是实现定义的,要么引发实现定义的信号。
int main(){
signed int a = 0b00000000001111111111111111111111;
signed int b = (a << 10) >> 10;
// b is: 0b11111111111111111111111111111111
signed short c = 0b0000000000111111;
signed short d = (c << 10) >> 10;
// d is: 0b111111
return 0;
}
Run Code Online (Sandbox Code Playgroud)
假设int
是 32 位和short
16 位,
为什么会b
得到符号扩展但d
没有得到符号扩展?我已经在 x64 上用 gdb 测试过这个,用 gcc 编译。
为了获得short
符号扩展,我不得不使用两个单独的变量,如下所示:
signed short f = c << 10;
signed short g = f >> 10;
// g is: …
Run Code Online (Sandbox Code Playgroud)