如何解释以下代码的输出? (与 C 中的类型转换有关)
How to explain the following code's output? (related to typecasting in C)
我从一个要求它的输出和解释的博客中看到这段代码片段。
#include<stdio.h>
int main()
{
int *const volatile p = 5;
printf("%d\n",5/2+p);
return 0;
}
这是我目前的理解:
1.The const 和 volatile 关键字在输出上下文中没有作用
2.This 代码是一个糟糕的代码,因为它在没有正确转换的情况下在 int* 和 int 之间执行算术运算。
3.I 最初假设输出应该是未定义的。博客说答案是 13(这是我实验发现的)。
Q.What 我不明白 13 是怎么得到的,是编译器未定义行为的结果吗?
4.I 使用 gdb 并确定症结在于操作 p+2
,其中 p 是指针(保持值 5),2 是整数除法 (5/2) 的结果.
此代码不正确:
int *const volatile p = 5;
不能将整数赋值给(或初始化,规则相同)指针,零值常量表达式的特殊情况除外。编译器必须给出诊断并可以拒绝该程序。如果它确实生成了一个可执行文件,语言规则将不再适用,因为代码违反了合同。
This code is a bad one as it performs arithmetic operation between an int* and an int without a proper cast.
您可以添加一个整数和一个指针而不用强制转换。事实上这是正常的做法。这意味着您将指针向前移动它指向的元素数。
尽管如此,指针运算必须保持在数组对象的范围内,或者指向最后一个。 (为此目的,非数组可以被视为大小为 1 的数组)。因此 5/2 + p
,即 p + 2
的有效性将取决于 p
是否已经指向一个数组,并且至少在它之后有另一个数组元素。在您的确切程序中它没有实际意义,因为该程序无效。
同样,printf
的问题也没有实际意义,因为我们已经 运行 关闭了 rails。但是 %d
的 ope运行d 必须具有 int
类型(它不能是指针)。
这确实是未定义的行为,但不是由于算法。由于错误的转换说明符打印指针 - %d
而不是 %p
并将参数转换为 void *
- 并用非零 int
值初始化指针.
算术本身:
如果 int
的大小是 4
/ sizeof(int) == 4
(因为它似乎在您的平台上)结果是 13
因为您增加了指针值乘以 2.
你递增 2
因为在 5/2
处正在进行整数运算并且 2.5
的小数部分将被丢弃。
从 5
开始时,它会增加 2 4
步。
sizeof(int) == 4
5 + (sizeof(int) * 2) == 13
或
5
+ 8
= 13
.
但如上所述,由于错误的转换说明符和用非零 int
值分配指针,这是未定义的行为。
对于指针的整数初始化:
对于错误的转换说明符:
根据sizeof(int) == 4,则命令
int *const volatile p = 5;
分配给指针,作为初始地址,(类似于)0x0005
5 不是一个值,而是地址,因为您还没有为它分配一些内存。然后,在printf()的结果上,结果是2+p,也就是指针运算。指针是 int 类型的,因此,您将其地址添加 2 个位置。因此,2 sizeof(int) 进一步是 2 * 4 = 8。最终,指针指向的地址是 5+8 = 13。
例如,您可以删除关键字 volatile 和 const 以了解它们不会影响结果。此外,您打印出指针引用的地址,但不是它的主题(或取消引用该地址的结果)
我从一个要求它的输出和解释的博客中看到这段代码片段。
#include<stdio.h>
int main()
{
int *const volatile p = 5;
printf("%d\n",5/2+p);
return 0;
}
这是我目前的理解:
1.The const 和 volatile 关键字在输出上下文中没有作用
2.This 代码是一个糟糕的代码,因为它在没有正确转换的情况下在 int* 和 int 之间执行算术运算。
3.I 最初假设输出应该是未定义的。博客说答案是 13(这是我实验发现的)。
Q.What 我不明白 13 是怎么得到的,是编译器未定义行为的结果吗?
4.I 使用 gdb 并确定症结在于操作 p+2
,其中 p 是指针(保持值 5),2 是整数除法 (5/2) 的结果.
此代码不正确:
int *const volatile p = 5;
不能将整数赋值给(或初始化,规则相同)指针,零值常量表达式的特殊情况除外。编译器必须给出诊断并可以拒绝该程序。如果它确实生成了一个可执行文件,语言规则将不再适用,因为代码违反了合同。
This code is a bad one as it performs arithmetic operation between an int* and an int without a proper cast.
您可以添加一个整数和一个指针而不用强制转换。事实上这是正常的做法。这意味着您将指针向前移动它指向的元素数。
尽管如此,指针运算必须保持在数组对象的范围内,或者指向最后一个。 (为此目的,非数组可以被视为大小为 1 的数组)。因此 5/2 + p
,即 p + 2
的有效性将取决于 p
是否已经指向一个数组,并且至少在它之后有另一个数组元素。在您的确切程序中它没有实际意义,因为该程序无效。
同样,printf
的问题也没有实际意义,因为我们已经 运行 关闭了 rails。但是 %d
的 ope运行d 必须具有 int
类型(它不能是指针)。
这确实是未定义的行为,但不是由于算法。由于错误的转换说明符打印指针 - %d
而不是 %p
并将参数转换为 void *
- 并用非零 int
值初始化指针.
算术本身:
如果 int
的大小是 4
/ sizeof(int) == 4
(因为它似乎在您的平台上)结果是 13
因为您增加了指针值乘以 2.
你递增 2
因为在 5/2
处正在进行整数运算并且 2.5
的小数部分将被丢弃。
从 5
开始时,它会增加 2 4
步。
sizeof(int) == 4
5 + (sizeof(int) * 2) == 13
或
5
+ 8
= 13
.
但如上所述,由于错误的转换说明符和用非零 int
值分配指针,这是未定义的行为。
对于指针的整数初始化:
对于错误的转换说明符:
根据sizeof(int) == 4,则命令
int *const volatile p = 5;
分配给指针,作为初始地址,(类似于)0x0005 5 不是一个值,而是地址,因为您还没有为它分配一些内存。然后,在printf()的结果上,结果是2+p,也就是指针运算。指针是 int 类型的,因此,您将其地址添加 2 个位置。因此,2 sizeof(int) 进一步是 2 * 4 = 8。最终,指针指向的地址是 5+8 = 13。 例如,您可以删除关键字 volatile 和 const 以了解它们不会影响结果。此外,您打印出指针引用的地址,但不是它的主题(或取消引用该地址的结果)