简体   繁体   中英

What does (int*) &var mean?

What is the meaning of (int*) &i ?

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

If it was * &i , I would understand. But in this case, this an " int " in there.

&i : means to take the address of i (which is a 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* 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)

*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!). One of those bytes will end up in i, but the others will over write the bytes neighboring 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 ). The program later writes an int value into the pointer. 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".

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.

As a preamble, when reading the text of the C standard, you need to know that the word "shall" has special significance. Any sentence containing the word "shall" imposes a hard requirement on either the program, or the compiler and runtime environment; 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). 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). Sometimes the text says "If X, then the behavior is undefined" instead; 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 .

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. Saving a value of type int * into a variable declared with that type is unproblematic. The next operation is *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:

  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. (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 ; int is not compatible with char , and int is not a character type. Therefore this program violates a requirement stated with the word "shall", which is not within a section named "constraints", and its behavior is undefined.

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. 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. 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.

(type)x is a type cast. It says to reinterpret or convert x to that type. With pointer types it always means reinterpret.

i is of type char . So &i is of type char * . Casting it to int * makes it of type int * so that p can be assigned to it.

When you subsequently write via p you'll be writing a whole int .

&i gives the address of the variable i . The (int *) converts that pointer, which is of type char * , into a pointer to 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). 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.

Without the (int*) , gcc would complain because pointer to carrots are not pointers to potatoes.

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.

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

Surely it's typecasting. i is a character variable and p is pointer to integer. 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. now p is point to i.

*p = 123455; // here you stored the value at &i with 123455.

when you'll print these value like

print (*p) // 123455

print (i) // some garbage -- because i is char (1 byte) and having the value of integer (4 byte). so i will take this as a decimal value and print the value accordingly.

but but let just say *p = 65;

print(*p) // 65

print(i) // A -- because char i = 65 and char 65 is 'A'

hope it'll help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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