如果我有:
unsigned int x;
x -= x;
Run Code Online (Sandbox Code Playgroud)
很明显,x 应该这样表达后是零,但到处看,他们说的行为,这种代码是不确定的,而不是仅仅值x(直到减法之前).
两个问题:
这段代码的行为确实未定义吗?
(例如,代码在兼容系统上崩溃[或更糟]?)
如果是这样,为什么 C表示行为是未定义的,当非常清楚x这里应该为零时?
即不在此定义行为给出的优势是什么?
很明显,编译器可以简单地使用它在变量中认为"方便"的任何垃圾值,并且它可以按预期工作......这种方法有什么问题?
在阅读Herb Sutter撰写的关键词(或其他名称)时,我遇到了以下几点:
没错,有些关键字在语义上等同于空格,这是一个美化的评论.
和
我们已经看到为什么C++语言将关键字视为保留字,我们已经看到两个关键字-auto和register--它们对C++程序没有任何语义差异.不要使用它们; 无论如何,它们只是空格,并且有更快的方式来输入空格.
如果关键字auto(可能不是在C++ 11中)并且register没有价值,那么它们为什么被创建和使用?
如果包含register变量之前没有任何区别
#include<stdio.h>
int main(){
register int a = 15;
printf("%d\n%d\n",&a,a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么上述程序会出错?
test_register.c:在函数'main'中:
test_register.c:4:2:错误:请求的寄存器变量'a'的地址
的printf( "%d \n%d \n",&A,A);
以下程序适用于C++.
#include<iostream>
int main(){
register int a = 15;
std::cout<<&a<<'\n'<<a;
return 0;
}
Run Code Online (Sandbox Code Playgroud) 是使用未初始化的变量作为src对memcpy用C未定义行为?
void foo(int *to)
{
int from;
memcpy(to, &from, sizeof(from));
}
Run Code Online (Sandbox Code Playgroud) 我刚刚在一个函数中找到了这行代码,这让我很困惑.这在任何情况下都有意义,还是未定义的行为?
char * acFilename = acFilename;
Run Code Online (Sandbox Code Playgroud)
编辑:编译器抱怨警告C4700,我正在使用未初始化的变量.
我偶然发现了Quora上的这段代码.
#include<stdio.h>
main(){
int $[]
={0x69, 0154,107,
'e',0x79,0157, 117,'v',0x6a}
,_,__;_=__^__;__=_;while(_<(-
(~(1<<3))+3)){(_==1<<1||_==
-(~(1<<3))||_==11)?putchar
(*($+(1>>1))):putchar(*(
__++ +$)),(_==1>>1||
_==1<<2||_==(1<<3
)-1)?putchar
(' '):1;
_++;
}
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出是i like you viji.它很动人,但很神秘.所以我用缩进格式化它以获得更好的主意.
main ()
{
int $[] = { 0x69, 0154, 107,
'e', 0x79, 0157, 117, 'v', 0x6a
}
, _, __;
_ = __ ^ __;
__ = _;
while (_ < (-(~(1 << 3)) + 3))
{
(_ == 1 << 1 || _ ==
-(~(1 << 3)) …Run Code Online (Sandbox Code Playgroud) 在C++ 14标准(n3797)中,左值转换的左值部分如下所示(强调我的):
4.1左值 - 右值 - 转换[conv.lval]
T可以将非函数非数组类型的glvalue(3.10)转换为prvalue.如果T是不完整类型,则需要进行此转换的程序格式不正确.如果T是非类类型,则prvalue的类型是cv-nonqualified versionT.否则prvalue的类型是T.当在未评估的操作数或其子表达式中发生左值到右值转换时(第5条),不访问引用对象中包含的值.在所有其他情况下,转换结果根据以下规则确定:
- 如果
T是(可能是cv限定的)std::nullptr_t则结果是空指针常量.- 否则,如果
T有类类型,则转换复制 -T从glvalue 初始化一个临时类型,转换的结果是临时的prvalue.- 否则,如果glvalue引用的对象包含无效指针值,则行为是实现定义的.
- 否则,如果
T是(可能是cv限定的)无符号字符类型,并且glvalue引用的对象包含不确定的值,并且该对象没有自动存储持续时间,或者glvalue是一元运算&符的操作数,或者它是绑定到引用,结果是一个未指定的值.- 否则,如果glvalue引用的对象具有不确定的值,则行为未定义.
- 否则,glvalue指示的对象是prvalue结果.
- [ 注:另见3.10]
这一段有什么意义(粗体)?
如果此段落不在此处,那么它适用的情况将导致未定义的行为.通常,我希望unsigned char在具有不确定值时访问值会导致未定义的行为.但是,这一段意味着
&或将其绑定到引用,或者unsigned char没有自动存储时间,然后转换产生一个未指定的值,而不是未定义的行为.
我是否正确地得出这个程序的结论:
#include <new>
#include <iostream>
// using T = int;
using T = unsigned char;
int main() {
T * array = new T[500];
for …Run Code Online (Sandbox Code Playgroud) c++ undefined-behavior language-lawyer lvalue-to-rvalue c++14
strlen返回终止空字符前面的字符数.的实现strlen可能是这样的:
size_t strlen(const char * str)
{
const char *s;
for (s = str; *s; ++s) {}
return(s - str);
}
Run Code Online (Sandbox Code Playgroud)
此特定实现取消引用s,其中s可能包含不确定的值.它相当于:
int a;
int* p = &a;
*p;
Run Code Online (Sandbox Code Playgroud)
因此,例如,如果有人这样做(导致strlen输出不正确):
char buffer[10];
buffer[9] = '\0';
strlen(buffer);
Run Code Online (Sandbox Code Playgroud)
是不确定的行为?
在malloc()用于分配内存空间之后,我很好奇指针究竟是什么?该联机帮助页告诉我calloc()初始化已分配的内存空间为零.
malloc()函数分配大小字节并返回指向已分配内存的指针. 内存未初始化.如果size为0,则malloc()返回NULL或一个以后可以成功传递给free()的唯一指针值.
和
calloc()函数为每个大小为字节的nmemb元素数组分配内存,并返回指向已分配内存的指针. 内存设置为零.如果nmemb或size为0,则calloc()返回NULL或一个以后可以成功传递给free()的唯一指针值.
我在C中为C(haha)创建了一个非常简短的示例程序:
int main() {
char *dynamic_chars;
unsigned amount;
printf("how much bytes you want to allocate?\n");
scanf("%d", &amount);
dynamic_chars = (char*)malloc(amount*sizeof(char));
printf("allocated:\n%s\n", dynamic_chars);
free(dynamic_chars);
return 0;
Run Code Online (Sandbox Code Playgroud)
}
但是,在执行此代码时,它只输出任何内容.如果我初始化内存,例如0xFFFF使用循环初始化每个字节,那么程序会向我显示我期望的内容.内存空间实际存在,因为我不会收到错误声称我正在尝试访问未初始化的变量.
由于内存空间通常不会被删除但被标记为可重写,我想知道如果通过执行我的程序,我是否应该能够看到以前使用的随机内存字节?但我什么都看不到,所以我真的很困惑malloc().
关于malloc()或者可能是内存使用的另一件事,关于我的程序是有趣的:如果我使用calloc(),分配内存,我可以通过例如监视来跟踪我的程序的实际内存使用情况.例如,如果我告诉我的程序,每次分配1.000.000.000字节的内存calloc()我将在我的系统监视器中看到以下内容:
c
malloc
initialization
dynamic-memory-allocation
我想使用https://research.swtch.com/sparse中描述的技巧在C++中构建一个密集的整数集.这种方法通过允许自己读取未初始化的内存来实现良好的性能.
如何在不触发未定义行为的情况下实现此数据结构,并且不会与Valgrand或ASAN等工具发生冲突?
编辑:似乎响应者正在关注"未初始化"这个词,并在语言标准的上下文中对其进行解释.对我而言,这可能是一个糟糕的词语选择 - 这里"未初始化"仅意味着它的价值对于算法的正确运行并不重要.显然可以安全地实现这个数据结构(LLVM在SparseMultiSet中实现它).我的问题是,最好和最有效的方法是什么?
在读取值时,未定义行为(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,还是有例外?