Tag: undefined behavior

是否在C中获取无效指针的值未定义或实现定义的行为?

根据此,获取无效指针的值是C ++中的实现定义行为。 现在考虑以下C程序: #include #include int main(void) { int* p=(int*)malloc(sizeof(int)); *p=3; printf(“%d\n”,*p); printf(“%p\n”,(void*)p); free(p); printf(“%p\n”,(void*)p); // Is this undefined or implementation defined in behaviour C? } 但是C中的行为也一样吗? 上述C程序的行为是否未定义或实现定义? C99 / C11标准对此有何看法? 请告诉我C99和C11的行为是否不同。

关于错误的atoi()的行为,我可以假设什么?

标准C库函数atoi在ISO 9899:2011中记录为: 7.22.1数字转换函数 1 atof , atoi , atol和atoll函数不需要影响错误的整数表达式errno的值。 如果无法表示结果的值,则行为未定义。 … 7.22.1.2 atoi , atol和atollfunction 概要 #include int atoi(const char *nptr); long int atol(const char *nptr); long long int atoll(const char *nptr); 描述 2 atoi , atol和atoll函数分别将nptr的字符串的初始部分转换为int , long int和long long int表示。 除了出错的行为,它们相当于 atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, […]

C标准是否要求平台不得定义超出标准规定的行为

C标准明确表示允许编译器/库组合使用以下代码执行任何操作: int doubleFree(char *p) { int temp = *p; free(p); free(p); return temp; } 但是,如果编译器不需要使用特定的捆绑库,那么C标准中是否有任何禁止库定义有意义行为的内容? 举一个简单的例子,假设代码是为具有引用计数指针的平台编写的,例如在p = malloc(1234); __addref(p); __addref(p); p = malloc(1234); __addref(p); __addref(p); 前两次调用free(p)会减少计数器但不释放内存。 编写用于此类库的任何代码自然只能用于这样的库(并且__addref()调用可能会在大多数其他库中失败),但是在许多情况下这样的特性可能会有所帮助,例如,有必要通过一个字符串重复到一个方法,该方法希望给出一个用strdup生成的字符串,因此在其上调用free 。 如果库会为某些操作定义一个有用的行为,例如双重释放指针,那么C标准中是否有任何内容可以授权编译器单方面破坏它?

是`y = x = x + 1;`未定义的行为?

这段代码是: y = x = x + 1; C中的未定义行为?

是否可以将int **和const int **替换为别名?

我的理解是这样的事情是可以的: const int ci = 42; const int *cip = &ci; int *ip = (int *)cip; int j = *ip; 那这个呢? const int ci = 42; const int *cip = &ci; const int **cipp = &cip; int **ipp = (int **)cipp; int j = **ipp;

逗号运算符和void表达式

我遇到了这段代码1 int return_printChar1() { // code // oops! no return statement } int return_printChar2() { // code return printf(“Return”); } int main() { int i; // some more code i = return_printChar2(); if((return_printChar1(),i)) { printf (“Gotcha”); } } 1:这不是一个真实的例子。 我的问题是“ 在C和C ++中是否很好地定义了代码片段的行为? ” 我的看法: 在C中,行为很明确,因为6.5.17说 逗号运算符的左操作数被计算为void表达式 ; 评估后有一个序列点 在C ++ 03中,行为很明确,因为5.18说 由逗号分隔的一对表达式从左到右计算,并且左表达式的值被丢弃 。 但是C ++ […]

可以保证UB在编译时被拒绝吗?

考虑这个程序: #include int main(void) { int x; while ( 1 == scanf(“%d”, &x) ) printf(“%c\n”, “hello”[x]); } 编译器必须成功编译,因为程序没有UB,只要用户不输入0范围之外的任何数字。 但是,根据这个线程, UB可以及时返回。 现在考虑这个程序: int main(void) { printf(“hello\n”); “hello”[6]; } 对此程序的任何调用都会导致未定义的行为,并且因为这可能是时间旅行,所以此程序在任何调用中的整个行为都是未定义的。 因此,编译器可以拒绝该程序而不生成可执行文件吗? (我们可能会说UB回到编译阶段!)

这会避免UB吗?

这个问题更像是一个学术问题,因为没有正当理由再编写自己的offsetof宏了。 不过,我已经在这里和那里看到了这个本土实现的弹出窗口: #define offsetof(s, m) ((size_t) &(((s *)0)->m)) 从技术上讲,这是取消引用NULL指针(AFAIKT): C11(ISO / IEC 9899:201x)§6.3.2.3指针第3节 值为0的整型常量表达式或类型为void *的表达式称为空指针常量 所以上面的实现是根据我阅读标准的方式,与写作相同: #define offsetof(s, m) ((size_t) &(((s *)NULL)->m)) 它确实让我想知道,通过改变一个微小的细节,下面的offsetof定义将是完全合法的,可靠的: #define offsetof(s, m) (((size_t)&(((s *) 1)->m)) – 1) 看起来,而不是0,1用作指针,我在结尾处减去1,结果应该是相同的。 我不再使用NULL指针了。 据我所知,结果是一样的 。 所以基本上:有没有理由在这个offsetof定义中使用1代替0可能不起作用? 在某些情况下它是否仍会导致UB,如果是这样的话:何时以及如何? 基本上,我在这里问的是: 我在这里遗漏了什么吗?

找到两个值的平均值的正确方法是什么?

我最近了解到整数溢出是C中未定义的行为(侧面问题 – 它是否也是C ++中的UB?) 通常在C编程中,您需要找到两个值a和b的平均值。 但是,执行(a+b)/2会导致溢出和未定义的行为。 所以我的问题是 – 在C中找到两个值a和b的平均值的正确方法是什么?

局部变量之前的GOTO

以下代码是否构成未定义的行为,因为我在变量声明之前跳转并通过指针使用它? 如果是这样,标准之间是否存在差异? int main() { int *p = 0; label1: if (p) { printf(“%d\n”, *p); return 0; } int i = 999; p = &i; goto label1; return -1; }