繁体   English   中英

(int *)&var是什么意思?

[英]What does (int*) &var mean?

(int*) &i的含义是什么?

  char i;
  int* p = (int*) &i;
  ...
  *p = 1234567892;
  ...

如果是* &i ,我会理解。 但在这种情况下,这里有一个“ int ”。

&i:表示取i的地址(这是一个char *)

(int*)&i :将指针强制转换为指向整数的指针(这样做是坏/错,但你告诉编译器这样做,所以它甚至不会发出警告)

int* p = (int*)&i; :一个声明,表示将i的指针存储在p中(并将其转换为:编译器甚至不会抱怨)

*p = 1234567892; :写这个值,它是p指向的址的几个字节(虽然p认为它指向一个int,但是为char!)。 其中一个字节将以i结尾,但其他字节将覆盖相邻i的字节。

构造(int *) &var ,其中var是一个char ,它接受一个指向var的指针,然后将它转换为一个不同类型的指针(即int )。 程序稍后将int值写入指针。 由于指针实际上指向一个char ,一个int值不适合,这会触发未定义的行为 ,这是一个奇特的名称,“字面上任何东西(你的计算机可以实际完成)可能发生 - 这个程序是错误的”。

编辑:根据要求,一些标准学来解释为什么这个程序有未定义的行为。 以下所有部分参考均为N1570 ,这是与C2011官方文本最接近的,可以在线免费访问。

作为序言,在阅读C标准的文本时,您需要知道“应该”一词具有特殊意义。 任何包含单词“shall”的句子都对程序或编译器和运行时环境提出了硬性要求; 你必须从上下文中找出哪一个。 该计划有两种硬性要求。 如果“约束”部分中出现“应该”的句子,那么编译器就需要诊断违规(第5.1.1.3节)(标准永远不会说明程序必须被拒绝 ,但这是通常在错误和警告)。 如果“shall”句子出现在其他地方,则编译器不需要诊断它,但是违反要求的程序具有未定义的行为(§4p1,2)。 有时文本会说“如果是X,那么行为是未定义的”; 后果没有区别。

首先,转换(int *) &varchar *转换为int *当且仅当 point-to- char的值与int类型的对象正确对齐时 ,才由§6.3.2.3p7明确允许。

指向对象类型的指针可以转换为指向不同对象类型的指针。 如果生成的指针未针对引用的类型正确对齐,则行为未定义。 否则,当再次转换回来时,结果将等于原始指针。

显示的代码中没有任何内容可以确保 var对于int进行了适当的对齐,因此程序可能已经触发了此时未定义的行为,但我们假设它正确对齐。 int *类型的值保存到使用该类型声明的变量中是没有问题的。 下一个操作是*p = integer_literal 这是对对象var 的存储值写访问 ,它必须遵守§6.5p6,7中的规则:

  1. 用于访问其存储值的对象的有效类型是对象的声明类型(如果有)。 [...更多关于如果对象没有声明类型会发生什么的文本; 这里不相关......]

  2. 对象的存储值只能由具有以下类型之一的左值表达式访问:

    • 与对象的有效类型兼容的类型,
    • 与对象的有效类型兼容的类型的限定版本,
    • 与对象的有效类型对应的有符号或无符号类型的类型,
    • 与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
    • 聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或者
    • 一个字符类型

对于像intchar这样的简单算术类型, 兼容 类型在剥离typedef之后意味着相同的类型。 (确切的定义分布在§§6.2.7,6.7.2,6.7.3和6.7.6。)对于这种分析而言,重要的是声明的var类型是char ,但是左值表达式*p type int ; intchar不兼容, int不是字符类型。 因此,该程序违反了单词“shall”所声明的要求,该要求不在名为“constraints”的部分中,并且其行为未定义。

注意最后一个项目符号点的不对称性。 任何对象都可以通过具有字符类型的左值表达式访问其存储值,但声明具有字符类型的对象可能无法由具有不兼容类型的左值表达式访问。 是的,这意味着访问一个大的阵列的字符(如数据从文件中读取的缓冲)“四在时间”的通过一个指向共同的成语int是,严格地说,无效。 许多编译器对这种情况的指针别名规则做了一个特殊的例外,以避免使该习惯用法无效。

但是,通过指向int的指针访问单个char也是无效的,因为(在大多数系统上) int大于char ,因此您读取或写入超出对象末尾的字节。 该标准并不打算将该案例与阵列案例区分开来,但无论如何它都会对你不利。

int *是一个类型 - 特别是它是指向int的指针。

(type)x是一个类型转换。 它说要重新解释或转换x到那种类型。 对于指针类型,它总是意味着重新解释。

ichar类型。 所以&ichar *类型。 将它转换为int *使其类型为int *以便可以为其分配p

当你随后通过p写时,你将写一个完整的int

&i给出变量i的地址。 (int *)将指针( char *类型(int *)转换为指向int的指针。

然后语句*p = 1234567892具有未定义的行为,因为p实际上指向单个char的地址,但是此表达式将该位置视为包含int (不同类型)。 在实践中,通常的结果是写入超过单个char内存位置,这可能导致数据中毒(例如,更改其他变量的值)到立即程序崩溃。

没有(int*) ,gcc会抱怨,因为指向胡萝卜的指针不是指向土豆的指针。

warning: initialization from incompatible pointer type [enabled by default]

因此,这种表示法只是意味着我知道我在这里做什么,认为它是指向不同类型的指针,即int。

这意味着您的程序即将崩溃并出现BUS错误

当然它是类型转换。 我是一个字符变量,p是指向整数的指针。 所以p =(int *)&i表示p存储的是i类型的地址,但是你有类型转换它,所以没关系。 现在p指向我。

* p = 123455; //这里你用123455将值存储在&i。

当你打印这些价值时

print(* p)// 123455

print(i)//一些垃圾 - 因为我是char(1字节)并且具有整数值(4字节)。 所以我将它作为十进制值并相应地打印该值。

但是,让我们说* p = 65;

print(* p)// 65

print(i)// A - 因为char i = 65而​​char 65是'A'

希望它能帮到你。

暂无
暂无

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

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