简体   繁体   English

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

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

What is the meaning of (int*) &i ? (int*) &i的含义是什么?

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

If it was * &i , I would understand. 如果是* &i ,我会理解。 But in this case, this an " int " in there. 但在这种情况下,这里有一个“ int ”。

&i : means to take the address of i (which is a char*) &i:表示取i的地址(这是一个char *)

(int*)&i : casts that pointer to be a pointer to integer (which is bad/wrong to do, but you told the compiler to do it so it won't even give a warning) (int*)&i :将指针强制转换为指向整数的指针(这样做是坏/错,但你告诉编译器这样做,所以它甚至不会发出警告)

int* p = (int*)&i; : a statement that says to store the pointer of i in p (and cast it too: the compiler won't even complain) :一个声明,表示将i的指针存储在p中(并将其转换为:编译器甚至不会抱怨)

*p = 1234567892; : write this value, which is several bytes to the base location pointed to by p (which although p thinks it points to an int, is to char!). :写这个值,它是p指向的址的几个字节(虽然p认为它指向一个int,但是为char!)。 One of those bytes will end up in i, but the others will over write the bytes neighboring i. 其中一个字节将以i结尾,但其他字节将覆盖相邻i的字节。

The construct (int *) &var , where var is a char , takes a pointer to var , and then converts it to a pointer of a different type (namely int ). 构造(int *) &var ,其中var是一个char ,它接受一个指向var的指针,然后将它转换为一个不同类型的指针(即int )。 The program later writes an int value into the pointer. 程序稍后将int值写入指针。 Since the pointer actually points to a char , an int value does not fit, which triggers undefined behavior , which is a fancy name for "literally anything (that your computer can physically accomplish) could happen -- this program is buggy". 由于指针实际上指向一个char ,一个int值不适合,这会触发未定义的行为 ,这是一个奇特的名称,“字面上任何东西(你的计算机可以实际完成)可能发生 - 这个程序是错误的”。

EDIT: As requested, some standardology to explain why this program has undefined behavior. 编辑:根据要求,一些标准学来解释为什么这个程序有未定义的行为。 All section references below are to N1570 , which is the closest approximation to the official text of C2011 that can be accessed online for free. 以下所有部分参考均为N1570 ,这是与C2011官方文本最接近的,可以在线免费访问。

As a preamble, when reading the text of the C standard, you need to know that the word "shall" has special significance. 作为序言,在阅读C标准的文本时,您需要知道“应该”一词具有特殊意义。 Any sentence containing the word "shall" imposes a hard requirement on either the program, or the compiler and runtime environment; 任何包含单词“shall”的句子都对程序或编译器和运行时环境提出了硬性要求; you have to figure out which from context. 你必须从上下文中找出哪一个。 There are two kinds of hard requirements on the program. 该计划有两种硬性要求。 If a "shall" sentence appears in a "constraints" section, then the compiler is required to diagnose violations (§5.1.1.3) (the standard never flat out says that a program must be rejected , but that's the usual line drawn between hard errors and warnings). 如果“约束”部分中出现“应该”的句子,那么编译器就需要诊断违规(第5.1.1.3节)(标准永远不会说明程序必须被拒绝 ,但这是通常在错误和警告)。 If a "shall" sentence appears somewhere else, then the compiler isn't required to diagnose it, but a program that violates the requirement has undefined behavior (§4p1,2). 如果“shall”句子出现在其他地方,则编译器不需要诊断它,但是违反要求的程序具有未定义的行为(§4p1,2)。 Sometimes the text says "If X, then the behavior is undefined" instead; 有时文本会说“如果是X,那么行为是未定义的”; there's no difference in the consequences. 后果没有区别。

First off, the conversion (int *) &var converts char * to int * , which is explicitly allowed by §6.3.2.3p7 if and only if the value of the pointer-to- char is properly aligned for an object of type int . 首先,转换(int *) &varchar *转换为int *当且仅当 point-to- char的值与int类型的对象正确对齐时 ,才由§6.3.2.3p7明确允许。

A pointer to an object type may be converted to a pointer to a different object type. 指向对象类型的指针可以转换为指向不同对象类型的指针。 If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. 如果生成的指针未针对引用的类型正确对齐,则行为未定义。 Otherwise, when converted back again, the result shall compare equal to the original pointer. 否则,当再次转换回来时,结果将等于原始指针。

There's nothing in the code shown that would ensure that var is aligned appropriately for an int , so the program might already have triggered undefined behavior at this point, but let's assume it is aligned correctly. 显示的代码中没有任何内容可以确保 var对于int进行了适当的对齐,因此程序可能已经触发了此时未定义的行为,但我们假设它正确对齐。 Saving a value of type int * into a variable declared with that type is unproblematic. int *类型的值保存到使用该类型声明的变量中是没有问题的。 The next operation is *p = integer_literal . 下一个操作是*p = integer_literal This is a write access to the stored value of the object var , which must obey the rules in §6.5p6,7: 这是对对象var 的存储值写访问 ,它必须遵守§6.5p6,7中的规则:

  1. The effective type of an object for an access to its stored value is the declared type of the object, if any. 用于访问其存储值的对象的有效类型是对象的声明类型(如果有)。 [... more text about what happens if the object has no declared type; [...更多关于如果对象没有声明类型会发生什么的文本; not relevant here ...] 这里不相关......]

  2. An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 对象的存储值只能由具有以下类型之一的左值表达式访问:

    • a type compatible with the effective type of the object, 与对象的有效类型兼容的类型,
    • a qualified version of a type compatible with the effective type of the object, 与对象的有效类型兼容的类型的限定版本,
    • a type that is the signed or unsigned type corresponding to the effective type of the object, 与对象的有效类型对应的有符号或无符号类型的类型,
    • a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, 与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
    • an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or 聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或者
    • a character type 一个字符类型

For simple arithmetic types like int and char , compatible type means the same type after stripping typedef s. 对于像intchar这样的简单算术类型, 兼容 类型在剥离typedef之后意味着相同的类型。 (The exact definition is spread over §§ 6.2.7, 6.7.2, 6.7.3, and 6.7.6.) What matters for this analysis is simply that the declared type of var is char , but the lvalue expression *p has type int ; (确切的定义分布在§§6.2.7,6.7.2,6.7.3和6.7.6。)对于这种分析而言,重要的是声明的var类型是char ,但是左值表达式*p type int ; int is not compatible with char , and int is not a character type. intchar不兼容, int不是字符类型。 Therefore this program violates a requirement stated with the word "shall", which is not within a section named "constraints", and its behavior is undefined. 因此,该程序违反了单词“shall”所声明的要求,该要求不在名为“constraints”的部分中,并且其行为未定义。

Note the asymmetry of the last bullet point. 注意最后一个项目符号点的不对称性。 Any object may have its stored value accessed by an lvalue expression with character type, but an object declared to have character type may not be accessed by an lvalue expression with an incompatible type. 任何对象都可以通过具有字符类型的左值表达式访问其存储值,但声明具有字符类型的对象可能无法由具有不兼容类型的左值表达式访问。 Yes, that means the common idiom of accessing a large array of characters (such as a buffer of data read from a file) "four at a time" via a pointer to int is, strictly speaking, invalid. 是的,这意味着访问一个大的阵列的字符(如数据从文件中读取的缓冲)“四在时间”的通过一个指向共同的成语int是,严格地说,无效。 Many compilers make a special exception to their pointer-aliasing rules for that case, to avoid invalidating that idiom. 许多编译器对这种情况的指针别名规则做了一个特殊的例外,以避免使该习惯用法无效。

However, accessing a single char via a pointer to int is also invalid because (on most systems) int is bigger than char , so you read or write bytes beyond the end of the object. 但是,通过指向int的指针访问单个char也是无效的,因为(在大多数系统上) int大于char ,因此您读取或写入超出对象末尾的字节。 The standard doesn't bother distinguishing that case from the array case, but it will blow up on you regardless. 该标准并不打算将该案例与阵列案例区分开来,但无论如何它都会对你不利。

int * is a type — specifically it is pointer to int. int *是一个类型 - 特别是它是指向int的指针。

(type)x is a type cast. (type)x是一个类型转换。 It says to reinterpret or convert x to that type. 它说要重新解释或转换x到那种类型。 With pointer types it always means reinterpret. 对于指针类型,它总是意味着重新解释。

i is of type char . ichar类型。 So &i is of type char * . 所以&ichar *类型。 Casting it to int * makes it of type int * so that p can be assigned to it. 将它转换为int *使其类型为int *以便可以为其分配p

When you subsequently write via p you'll be writing a whole int . 当你随后通过p写时,你将写一个完整的int

&i gives the address of the variable i . &i给出变量i的地址。 The (int *) converts that pointer, which is of type char * , into a pointer to int . (int *)将指针( char *类型(int *)转换为指向int的指针。

The statement *p = 1234567892 then has undefined behaviour, since p actually points to an address of a single char , but this expression treats that location as if it contains an int (different type). 然后语句*p = 1234567892具有未定义的行为,因为p实际上指向单个char的地址,但是此表达式将该位置视为包含int (不同类型)。 In practice, the usual result is to write to memory locations past the single char , which can cause anything from data poisoning (eg changing values of other variables) to an immediate program crash. 在实践中,通常的结果是写入超过单个char内存位置,这可能导致数据中毒(例如,更改其他变量的值)到立即程序崩溃。

Without the (int*) , gcc would complain because pointer to carrots are not pointers to potatoes. 没有(int*) ,gcc会抱怨,因为指向胡萝卜的指针不是指向土豆的指针。

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

Thus, this notation just means ok I know what I'm doing here, consider it a pointer to different type, ie an int. 因此,这种表示法只是意味着我知道我在这里做什么,认为它是指向不同类型的指针,即int。

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

Surely it's typecasting. 当然它是类型转换。 i is a character variable and p is pointer to integer. 我是一个字符变量,p是指向整数的指针。 so p= (int *) &i means p is storing the address of i which is of type char but you have type cast it, so it's fine with that. 所以p =(int *)&i表示p存储的是i类型的地址,但是你有类型转换它,所以没关系。 now p is point to i. 现在p指向我。

*p = 123455; * p = 123455; // here you stored the value at &i with 123455. //这里你用123455将值存储在&i。

when you'll print these value like 当你打印这些价值时

print (*p) // 123455 print(* p)// 123455

print (i) // some garbage -- because i is char (1 byte) and having the value of integer (4 byte). print(i)//一些垃圾 - 因为我是char(1字节)并且具有整数值(4字节)。 so i will take this as a decimal value and print the value accordingly. 所以我将它作为十进制值并相应地打印该值。

but but let just say *p = 65; 但是,让我们说* p = 65;

print(*p) // 65 print(* p)// 65

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

hope it'll help you. 希望它能帮到你。

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

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