简体   繁体   English

下面代码的output怎么解释? (与 C 中的类型转换有关)

[英]How to explain the following code's output? (related to typecasting in C)

I came across this code snippet from a blog who was asking for it's output and an explanation.我从一个博客中看到了这个代码片段,他要求它是 output 和解释。

#include<stdio.h>

int main()
{
    int *const volatile p = 5;
    printf("%d\n",5/2+p);
    return 0;
}

Here's what I understand so far:到目前为止,这是我的理解:

1.The const and volatile keywords don't contribute in context of the output 1. const 和 volatile 关键字在 output 的上下文中不起作用

2.This code is a bad one as it performs arithmetic operation between an int* and an int without a proper cast. 2.这段代码很糟糕,因为它在没有适当转换的情况下在 int* 和 int 之间执行算术运算。

3.I initially assumed the output should be undefined. 3.我最初假设 output 应该是未定义的。 The blog stated the answer to be 13 (which what i experimentally found).博客说答案是 13(我通过实验发现的)。

Q.What I don't understand is how was 13 obtained, was it the outcome of an undefined behavior from the compiler?问:我不明白 13 是如何获得的,是编译器未定义行为的结果吗?

4.I used gdb and determined that the crux lies in the operation p+2 , where p is the pointer (holding value 5) and 2 is the outcome of integer division (5/2). 4.我使用了gdb,确定关键在于操作p+2 ,其中p是指针(保存值5),2是integer除法(5/2)的结果。

This code is incorrect:此代码不正确:

int *const volatile p = 5;

An integer cannot be assigned to (or initialize, the rules are the same) a pointer, except for the special case of a constant expression of zero value.不能将 integer 分配给(或初始化,规则相同)指针,但零值常量表达式的特殊情况除外。 The compiler must give a diagnostic and can reject the program.编译器必须给出诊断并且可以拒绝该程序。 And if it does generate an executable anyway, the language rules no longer apply since the code broke the contract.如果它确实生成了一个可执行文件,那么语言规则将不再适用,因为代码违反了合同。

This code is a bad one as it performs arithmetic operation between an int* and an int without a proper cast.这段代码很糟糕,因为它在没有适当转换的情况下在 int* 和 int 之间执行算术运算。

You are allowed to add an integer and a pointer without a cast.您可以添加一个 integer 和一个没有强制转换的指针。 In fact that is normal practice.事实上,这是正常的做法。 It means that you advance the pointer by that number of elements of what it is pointing to.这意味着您将指针推进它所指向的元素的数量。

Notwithstanding the above though, pointer arithmetic must stay within the bounds of an array object, or point one-past-the-end.尽管如此,指针算术必须保持在数组 object 的范围内,或者指向过去的一端。 (Non-arrays can be treated as arrays of size 1 for this purpose). (为此,非数组可以被视为大小为 1 的 arrays)。 So the validity of 5/2 + p , ie p + 2 , would depend on whether p was already pointing into an array and there was another array element after it at least.所以5/2 + p的有效性,即p + 2 ,将取决于p是否已经指向一个数组,并且至少在它之后还有另一个数组元素。 In your exact program it's moot since the program is invalid.在您的确切程序中,它没有实际意义,因为该程序无效。

Similarly, the question of the printf is also moot since we already ran off the rails.同样, printf的问题也没有实际意义,因为我们已经偏离了轨道。 But the operand for %d must have type int (it cannot be a pointer).但是%d的操作数必须是int类型(不能是指针)。

It is undefined behavior indeed, but not due to the arithmetic.这确实是未定义的行为,但不是由于算术。 Due to the wrong conversion specifier to print a pointer - %d instead of %p with an argument cast to void * - and to initialize a pointer by an non-zero int value.由于错误的转换说明符来打印指针 - %d而不是%p带有强制转换为void *的参数 - 并用非零int值初始化指针。

To the arithmetic itself:对于算术本身:

If the size of an int is 4 / sizeof(int) == 4 (as it seems to be on your platform) the result is 13 because you increment the pointer value by 2.如果int的大小是4 / sizeof(int) == 4 (因为它似乎在您的平台上)结果是13 ,因为您将指针值增加了 2。

You increment by 2 because at 5/2 is happening integer arithmetic and the fraction part of 2.5 will be discarded.你增加2因为在5/2发生 integer 算术和2.5的小数部分将被丢弃。

When starting from 5 , it adds 2 4 er steps.5开始时,它增加了 2 4 er 步骤。

sizeof(int) == 4
5 + (sizeof(int) * 2) == 13

OR或者

5 + 8 = 13 . 5 + 8 = 13

But as said above, it is undefined behavior due to the wrong conversion specifier and to assign a pointer by an non-zero int value.但如上所述,由于错误的转换说明符和通过非零int值分配指针,这是未定义的行为。


For the integer initialization of the pointer:对于 integer 的指针初始化:

"Pointer from integer/integer from pointer without a cast" issues “来自整数的指针/来自没有强制转换的指针的整数”问题

For the wrong conversion specifier:对于错误的转换说明符:

How to print the address value of a pointer in a C program?如何在 C 程序中打印指针的地址值?

Depending on the fact that the sizeof(int) == 4, then the command根据 sizeof(int) == 4 的事实,然后命令

int *const volatile p = 5;

assigns to the pointer, as initial address, (something like) 0x0005 5 is not a value, but the address, as you have not allocated some memory for it.分配给指针,作为初始地址,(类似于)0x0005 5 不是一个值,而是地址,因为您没有为它分配一些 memory。 Then, on the result of printf(), the result is 2+p, which means pointer arithmetics.然后,在 printf() 的结果上,结果是 2+p,这意味着指针算术。 The pointer is of type int, therefore, you add on its address 2 positions away.指针是 int 类型的,因此,在它的地址上添加 2 个位置。 Thus, 2 sizeof(int) further is 2 * 4 = 8. Conclusively, the address where the pointer points is 5+8 = 13. For example, you can remove the keywords volatile and const to understand that they do not affect the result.因此,2 sizeof(int) 进一步为 2 * 4 = 8。最终,指针指向的地址是 5+8 = 13。例如,您可以删除关键字volatile 和 const以了解它们不会影响结果. Also, you print out the address where the pointer refers, but not the subject of it(or the result of de-referencing to that address)此外,您打印出指针所指的地址,但不是它的主题(或取消引用该地址的结果)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM