考虑这个程序:
#include <stdio.h>
int main(void)
{
unsigned int a;
printf("%u %u\n", a^a, a-a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是不确定的行为?
从表面上看,它a是一个未初始化的变量.所以这指向未定义的行为.但是a^a并且a-a等于0所有的价值a,至少我认为是这样的.有可能有某种方式来证明行为是明确定义的吗?
这到底发生了什么?
a << -5
显然它没有正确转变.但我正在阅读的这本书指出:
在一台机器上,这个表达式实际上是左移27位
我的问题是; 为什么?什么原因导致27位左移?在使用负移位计数换档时会发生什么?谢谢.
C11§6.5.7第5段:
结果
E1 >> E2是E1右移位E2位置.如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是商的整数部分E1 / 2*^E2.如果E1具有有符号类型和负值,则结果值是实现定义的.
但是,viva64参考文档说:
Run Code Online (Sandbox Code Playgroud)int B; B = -1 >> 5; // unspecified behavior
我在GCC上运行了这个代码,它总是给出一个输出-1.
所以,标准说"如果E1有一个带符号的类型和一个负值,结果值是实现定义的",但该文档说这-1>>5;是未指定的行为.
那么,-1>>5;C中是否有未指明的行为?哪个是对的?
我在cppreference.com上看到了以下示例
int x; // OK: the value of x is indeterminate
int y = x; // undefined behavior
Run Code Online (Sandbox Code Playgroud)
这里int y = x;是未定义的行为,因为它x是未初始化的.
但,
unsigned char c; // OK: the value of c is indeterminate
unsigned char d = c; // OK: the value of d is indeterminate
Run Code Online (Sandbox Code Playgroud)
这里unsigned char d = c;是不确定的行为,但unsigned char c;也是一个未初始化的变量.
那么,为什么unsigned char d不确定的价值呢?
当我使用Clang(-O3)或MSVC(/O2)编译并运行此代码时...
#include <stdio.h>
#include <time.h>
static int const N = 0x8000;
int main()
{
clock_t const start = clock();
for (int i = 0; i < N; ++i)
{
int a[N]; // Never used outside of this block, but not optimized away
for (int j = 0; j < N; ++j)
{
++a[j]; // This is undefined behavior (due to possible
// signed integer overflow), but Clang doesn't see it
}
}
clock_t const finish = …Run Code Online (Sandbox Code Playgroud) 具体来说,是下面的代码,标记下方的行,好吗?
struct S{
int a;
};
#include <stdlib.h>
int main(){
struct S *p;
p = malloc(sizeof(struct S) + 1000);
// This line:
*(&(p->a) + 1) = 0;
}
Run Code Online (Sandbox Code Playgroud)
人们在这里争论,但没有人给出令人信服的解释或参考.
他们的论点略有不同,但基本相同
typedef struct _pack{
int64_t c;
} pack;
int main(){
pack *p;
char str[9] = "aaaaaaaa"; // Input
size_t len = offsetof(pack, c) + (strlen(str) + 1);
p = malloc(len);
// This line, with similar intention:
strcpy((char*)&(p->c), str);
// ^^^^^^^
Run Code Online (Sandbox Code Playgroud) int main() {
int j = 0;
int i = 0;
for (j = 0; j < 5; j++) {
printf("Iteration %d : %d ", j + 1, i);
int i;
printf("%d", i);
i = 5;
printf("\n");
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码生成以下输出:
Iteration 1 : 0 0
Iteration 2 : 0 5
Iteration 3 : 0 5
Iteration 4 : 0 5
Iteration 5 : 0 5
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么printf迭代2,3,4,5中的第二个值是5.
我为什么第一个值在每个迭代是0的理解是,范围i在for环是局部的,但只要我们进入一个新的迭代的破坏i在被宣布for循环.
但我无法弄清楚为什么这个值在第二个时变为5 printf.
我刚才下面的代码可以用铿锵/ GCC /铛++/G ++编译注意到,使用c99,c11,c++11标准.
int main(void) {
int i = i;
}
Run Code Online (Sandbox Code Playgroud)
甚至-Wall -Wextra,没有一个编制者甚至报告警告.
通过修改代码int i = i + 1;和使用-Wall,他们可能会报告:
why.c:2:13: warning: variable 'i' is uninitialized when used within its own initialization [-Wuninitialized]
int i = i + 1;
~ ^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
我的问题:
在块范围内考虑此代码:
struct foo { unsigned char a; unsigned char b; } x, y;
x.a = 0;
y = x;
Run Code Online (Sandbox Code Playgroud)
C [N1570] 6.3.2.1 2说"如果左值指定了一个自动存储持续时间的对象,该对象可以用寄存器存储类声明(从未使用过它的地址),并且该对象未初始化(未使用初始化程序声明)在使用之前没有对它进行任何分配),行为是不确定的."
虽然已为某个成员x分配了一个值,但x尚未执行任何分配,并且尚未对其进行分配.因此,看起来6.3.2.1 2告诉我们xin 的行为y = x是未定义的.
但是,如果我们为每个成员分配了一个值x,那么x为了6.3.2.1 2的目的考虑未初始化似乎是不合理的.
(1)严格来说,标准中是否有任何内容导致6.3.2.1 2不适用于(未定义)上述代码?
(2)假设我们正在修改标准或确定对6.3.2.1的合理修改2,是否有理由偏好以下其中一项而不是其他?(a)6.3.2.1 2不适用于结构.(b)如果一个结构的至少一个成员被赋予了一个值,则该结构在6.3.2.1的目的下不是未初始化的.(c)如果一个结构的所有已命名的1个成员都被赋予了一个值,那么该结构是为6.3.2.1的目的而未初始化2.
1结构可能具有未命名的成员,因此并不总是可以为结构的每个成员分配值.(即使结构初始化,未命名的成员也具有不确定的值,每6.7.9 9.)
c ×8
c++ ×3
gcc ×2
struct ×2
clang ×1
declaration ×1
loops ×1
scope ×1
shadowing ×1
visual-c++ ×1