I always wanted to know what is the real thing difference of how the compiler see a pointer to a struct (in C suppose) and a struct itself.
struct person p;
struct person *pp;
pp->age, I always imagine that the compiler does: "value of pp + offset of atribute "age" in the struct".
But what it does with person.p? It would be almost the same. For me "the programmer", p is not a memory address, its like "the structure itself", but of course this is not how the compiler deal with it.
My guess is it's more of a syntactic thing, and the compiler always does (&p)->age.
I'm correct?
p->q is essentially syntactic sugar for (*p).q in that it dereferences the pointer p and then goes to the proper field q within it. It saves typing for a very common case (pointers to structs).
In essence, -> does two deferences (pointer dereference, field dereference) while . only does one (field dereference).
Due to the multiple-dereference factor, -> can't be completely replaced with a static address by the compiler and will always include at least address computation (pointers can change dynamically at runtime, thus the locations will also change), whereas in some cases, . operations can be replaced by the compiler with an access to a fixed address (since the base struct's address can be fixed as well).
Updated (see comments):
You have the right idea, but there is an important difference for global and static variables only: when the compiler sees p.age for a global or static variable, it can replace it, at compile time, with the exact address of the age field within the struct.
In contrast, pp->age must be compiled as "value of pp + offset of age field", since the value of pp can change at runtime.
The two statements are not equivalent, even from the "compiler perspective". The statement p.age translates to the address of p + the offset of age, while pp->age translates to the address contained in pp + the offset of age.
The address of a variable and the address contained in a (pointer) variable are very different things.
Say the offset of age is 5. If p is a structure, its address might be 100, so p.age references address 105.
But if pp is a pointer to a structure, its address might be 100, but the value stored at address 100 is not the beginning of a person structure, it's a pointer. So the value at address 100 (the address contained in pp) might be, for example, 250. In that case, pp->age references address 255, not 105.
Since p is a local (automatic) variable, it is stored in the stack. Therefore the compiler accesses it in terms of offset with regard to the stack pointer (SP) or frame pointer (FP or BP, in architectures where it exists). In contrast, *p refers to a memory address [usually] allocated in the heap, so the stack registers are not used.
This is a question I've always asked myself.
v.x, the member operator, is valid only for structs.
v->x, the member of pointer operator, is valid only for struct pointers.
So why have two different operators, since only one is needed? For example, only the . operator could be used; the compiler always knows the type of v, so it knows what to do: v.x if v is a struct, (*v).x if v is a struct pointer.
I have three theories:
temporary shortsightedness by K&R (which theory I'd like to be false)
making the job easier for the compiler (a practical theory, given the conception time of C :)
readability (which theory I prefer)
Unfortunately, I don't know which one (if any) is true.
In both cases the structure and its members are addressed by
address(person) + offset(age)
Using p with a struct stored in the stack memory gives the compiler more options to optimize memory usage. It could store the age only, instead of the whole struct if nothing else is used - this makes addressing with the above function fail (I think reading the address of a struct stops this optimization).
A struct on the stack may have no memory address at all. If the struct is small enough and only lives a short time it can be mapped to some of the processors registers (same as for the optimization above for reading the address).
The short answer: when the compiler does not optimize you are right. As soon as the compiler starts optimizing only what the c standard specifies is guaranteed.
Edit: Removed flawed stack/heap location for "pp->" since the pointed to struct can be on both heap and stack.
Related
I'm reading this book, and I found this code snippet in Chapter 14.
struct kobject *cdev_get(struct cdev *p)
{
struct module *owner = p->owner;
struct kobject *kobj;
if (owner && !try_module_get(owner))
return NULL;
kobj = kobject_get(&p->kobj);
if (!kobj)
module_put(owner);
return kobj;
}
I understand that this dereferences p, a cdev pointer then accesses its owner member
p->owner // (*p).owner
However, how does this work? It seems like it dereferences the memory address of a cdev pointer then access the kobj member of the pointer itself?
&p->kobj // (*(&p)).kobj
I thought pointers weren't much more than memory addresses so I don't understand how they can have members. And if it was trying to access a member of the pointer itself, why not just do p.kobj?
As per p being defined as struct cdev *p, p is very much a "memory address" but that's not all it is - it also has a type attached to it.
Since the expression *ptr is "the object pointed to by ptr", that also has the type attached, so you can logically do (*ptr).member.
And, since ptr->member is identical to (*ptr).member, it too is valid.
Bottom line is, your contention that "pointers [aren't] much more than memory addresses" is correct. But they are a little bit more :-)
In terms of &ptr->member, you seem to be reading that as (&ptr)->member, which is not correct.
Instead, as per C precedence rules, it is actually &(ptr->member), which means the address of the member of that structure.
These precedence rules are actually specified by the ISO C standard (C11 in this case). From 6.5 Expressions, footnote 85:
The syntax specifies the precedence of operators in the evaluation of an expression, which is the same as the order of the major subclauses of this subclause, highest precedence first.
And, since 6.5.2 Postfix operators (the bit covering ->) comes before 6.5.3 Unary operators (the bit covering &), that means -> evaluates first.
A pointer variable contains a memory address. What you need to consider is how the C programming language is used to write source code in a higher level language that is then converted for you into the machine code actually used by the computer.
The C programming language is a language that was designed to make using the hardware of computers easier than using assembly code or machine code. So it has language features to make it easier to write source code that is more readable and easier to understand than assembly code.
When we declare a pointer variable in C as a pointer to a type what we are telling the compiler is the type of the data at the memory location whose address is stored in the pointer. However the compiler does not really know if we are telling it the truth or not. The key thing to remember is that an actual memory address does not have a type, it is just an address. Any type information is lost once the compiler compiles the source code into machine code.
A struct is a kind of template or pattern or stencil that is used to virtually overlay a memory area to determine how the bytes in the memory area are to be interpreted. A programmer can use higher level language features when working with data without having to know about memory addresses and offsets.
If a variable is defined as the struct type then a memory area large enough to hold the struct is allocated and the compiler will figure out member offsets for you. If a variable is defined as a pointer to a memory area that is supposed to contain the data for that type again the compiler will figure out member offsets for you. However it is up to you to have the pointer variable containing the correct address.
So if you have a struct something like the following:
struct _tagStruct {
short sOne;
short sTwo;
};
And you then use it such as:
struct _tagStruct one; // allocate a memory area large enough for a struct
struct _tagStruct two; // allocate a memory area large enough for a struct
struct _tagStruct *three; // a pointer to a memory area to be interpreted as a struct
one.sOne = 5; // assign a value to this memory area interpreted as a short
one.sTwo = 7; // assign a value to this memory area interpreted as a
two = one; // make a copy of the one memory area in another
three = &one; // assign an address of a memory area to our pointer
three->sOne = 405; // modify the memory area pointed to, one.sOne in this case
You do not need to worry about the details of the memory layout of the struct and offsets to the struct members. And assigning one struct to another is merely an assignment statement. So this all works at a human level rather than a machine level of thinking.
However what if I have a function, short funcOne (short *inoutOne), that I want to use with the sOne member of the struct one? I can just do this funcOne(&one.sOne) which calls the function funcOne() with the address of the sOne member of the struct _tagStruct variable one.
A typical implementation of this in machine code is to load the address of the variable one into a register, add the offset to the member sOne and then call the function funcOne() with this calculated address.
I could also do something similar with a pointer, funcOne(&three->sOne).
A typical implementation of this in machine code is to load the contents of the pointer variable three into a register, add the offset to the member sOne and then call the function funcOne() with this calculated address.
So in one case we load the address of a variable into a register before adding the offset and in the second case we load the contents of a variable into a register before adding the offset. In both cases the compiler is using an offset which is usually the number of bytes from the beginning of the struct to the member of the struct. In the case of the first member, sOne of struct _tagStruct this offset would be zero bytes since it is the first member of the struct. For many compilers the offset of the second member, sTwo, would be two bytes since the size of a short is two bytes.
However the compiler is free to make choices about the layout of a struct unless explicitly told otherwise so on some computers the offset of member sTwo may be four bytes in order to generate more efficient machine code.
So using the C programming language allows us some degree of independence from the underlying computer hardware unless there is some reason for us to actually deal with those details.
The C language standard specifies operator precedence meaning when different operators are mixed together in a statement and parenthesis are not used to specify an exact order of evaluation on the expression then the compiler will use these standard rules to determine how to turn the C language expression into the proper machine code (see Operator precedence table for the C programming language ).
Both the dot (.) operator and the dereference (->) operator have equal precedence as well as the highest precedence of the operators. So when you write an expression such as &three->sOne then what the compiler does is turn it into an express that looks like &(three->sOne). This is using the address of operator to calculate an address of the sOne member of the memory area pointed to by the pointer variable three.
A different expression would be (&three)->sOne which actually should throw a compiler error since &three is not a pointer to a memory area holding a struct _tagStruct value but is instead a pointer to a pointer since three is a pointer to a variable of type struct _tagStruct and not a variable of type struct _tagStruct.
->member has higher precedence than &.
&p->kobj
parses as
&(p->kobj)
i.e. it's taking the address of the kobj member of the struct pointed to by p.
You have the order of operations wrong:
&p->kobj // &(p->kobj)
I'm learning about pointers and have been told this: "The purpose of pointers is to allow you to manually, directly access a block of memory."
Say I have int var = 5;. Can't I use the variable 'var' to access the block of memory where the value 5 is stored, since I can change the value of the variable whenever I want var = 6;? Do I really need a pointer when I can access any variable's value just by using its variable, instead of using a pointer that points to the address where the value is stored?
"The purpose of pointers is to allow you to manually, directly access a block of memory."
This is not always true. Consider
*(int*)(0x1234) = some_value;
this is "direct" memory access. Though
int a = some_value, *ptr = &a;
*ptr = some_other_value;
you are now accessing a indirectly.
Can't I use the variable 'var' to access the block of memory where the
value 5 is stored, since I can change the value of the variable
whenever I want var = 6; ?
Surely; but the semantics is different.
Do I really need a pointer when I can access any variable's value just by using its variable, instead of using a pointer that points to the address where the value is stored?
No, you don't. Consider the first example: within the scope where a has been declared, modifying its value through ptr is rather pointless! However, what if you are not within the scope of a? That is
void foo(int x)
{
x = 5;
}
int main(void)
{
int x = 10;
foo(x);
}
In foo, when you do x = 5, there is an ambiguity: do you want to modify foo::x or main::x? In the latter case that has to be "requested" explicitly and the fact that happens through pointers -or, better, through indirection- is a coincidence and a language choice. Other languages have others.
Pointer types have some traits that make them really useful:
It's guaranteed that a pointer will be so large that it can hold any address that is supported by the architecture (on x86, that is 32 bits a.k.a. 4 bytes, and an x64 64 bits a.k.a. 8 bytes).
Dereferencing and indexing the memory is done per object, not per byte.
int buffer[10];
char*x = buffer;
int*y = (int*)buffer;
That way, x[1] isn't y[1]
Both is not guaranteed if you use simple ints to hold your values. The first trait is at least guaranteed by uintptr_t (not by size_t though, although most of the time they have the same size - except that size_t can be 2 bytes in size on systems with segmented memory layout, while uintptr_t is still 4 bytes in size).
While using ints might work at first, you always:
have to turn the value into a pointer
have to dereference the pointer
and have to make sure that you don't go beyond certain values for your "pointer". For a 16 bit int, you cannot go beyond 0xFFFF, for 32 bit it's 0xFFFF FFFF - once you do, your pointer might overflow without you noticing it until it's too late.
That is also the reason why linked lists and pointers to incomplete types work - the compiler already knows the size of the pointers you are going to you, and just allocates memory for them. All pointers have the same size (4 or 8 bytes on 32-bit/64-bit architectures) - the type that you assign them just tells the compiler how to dereference the value. char*s take up the same space as void*s, but you cannot dereference void*s. The compiler won't let you.
Also, if you are just dealing with simple integers, there's a good chance that you will slow down your program significantly do to something called "aliasing", which basically forces the compiler to read the value of a given address all the time. Memory accesses are slow though, so you want to optimized these memory accesses out.
You can compare a memory address to a street address:
If you order something, you tell the shop your address, so that they can send you what you bought.
If you don't want to use your address, you have to send them your house, such that they can place the parcel inside.
Later they return your house to you. This is a bit more cumbersome than using the address!
If you're not at home, the parcel can be delivered to your neighbor if they have your address, but this is not possible if
you sent them your house instead.
The same is true for pointers: They are small and can be transported easily, while the object they point to
might be large, and less easily transportable.
With pointer arithmetics, pointers can also be used to access other objects than the one they originally pointed to.
You call a function from main() or from another function, the function you called can only return 1 value.
Let say you want 3 values changed, you pass them to the called function as pointers. That way you don't have to use global values.
One possible advantage is that it can make it easier to have one function modify a variable that will be used by many other functions. Without pointers, your best option is for the modifying function to return a value to the caller and then to pass this value to the other functions. That can lead to a lot of passing around. Instead, you can give the modifying function a pointer where it stores its output, and all the other functions directly access that memory address. Kind of like global variables.
I have a
LS_Led* LS_vol_leds[10];
declared in one C module, and the proper externs in the other modules that access it.
In func1() I have this line:
/* Debug */
LS_Led led = *(LS_vol_leds[0]);
And it does not cause an exception. Then
I call func2() in another C module (right after above line), and do the same line, namely:
/* Debug */
LS_Led led = *(LS_vol_leds[0]);`
first thing, and exception thrown!!!
I don't think I have the powers to debug this one on my own.
Before anything LS_vol_leds is initialized in func1() with:
LS_vol_leds[0] = &led3;
LS_vol_leds[1] = &led4;
LS_vol_leds[2] = &led5;
LS_vol_leds[3] = &led6;
LS_vol_leds[4] = &led7;
LS_vol_leds[5] = &led8;
LS_vol_leds[6] = &led9;
LS_vol_leds[7] = &led10;
LS_vol_leds[8] = &led11;
LS_vol_leds[9] = &led12;
My externs look like
extern LS_Led** LS_vol_leds;
So does that lead to disaster and I how do I prevent disaster?
Thanks.
This leads to disaster:
extern LS_Led** LS_vol_leds;
You should try this instead:
extern LS_Led *LS_vol_leds[];
If you really want to know why, you should read Expert C Programming - Deep C Secrets, by Peter Van Der Linden (amazing book!), especially chapter 4, but the quick answer is that this is one of those corner cases where pointers and arrays are not interchangeable: a pointer is a variable which holds the address of another one, whereas an array name is an address. extern LS_Led** LS_vol_leds; is lying to the compiler and generating the wrong code to access LS_vol_leds[i].
With this:
extern LS_Led** LS_vol_leds;
The compiler will believe that LS_vol_leds is a pointer, and thus, LS_vol_leds[i] involves reading the value stored in the memory location that is responsible for LS_vol_leds, use that as an address, and then scale i accordingly to get the offset.
However, since LS_vol_leds is an array and not a pointer, the compiler should instead pick the address of LS_vol_leds directly. In other words: what is happening is that your original extern causes the compiler to dereference LS_vol_leds[0] because it believes that LS_vol_leds[0] holds the address of the pointed-to object.
UPDATE: Fun fact - the back cover of the book talks about this specific case:
So that's why extern char *cp isn't the same as extern char cp[]. I
knew that it didn't work despite their superficial equivalence, but I
didn't know why. [...]
UPDATE2: Ok, since you asked, let's dig deeper. Consider a program split into two files, file1.c and file2.c. Its contents are:
file1.c
#define BUFFER_SIZE 1024
char cp[BUFFER_SIZE];
/* Lots of code using cp[i] */
file2.c
extern char *cp;
/* Code using cp[i] */
The moment you try to assing to cp[i] or use cp[i] in file2.c will most likely crash your code. This is deeply tight into the mechanics of C and the code that the compiler generates for array-based accesses and pointer-based accesses.
When you have a pointer, you must think of it as a variable. A pointer is a variable like an int, float or something similar, but instead of storing an integer or a float, it stores a memory address - the address of another object.
Note that variables have addresses. When you have something like:
int a;
Then you know that a is the name for an integer object. When you assign to a, the compiler emits code that writes into whatever address is associated with a.
Now consider you have:
char *p;
What happens when you access *p? Remember - a pointer is a variable. This means that the memory address associated with p holds an address - namely, an address holding a character. When you assign to p (i.e., make it point to somewhere else), then the compiler grabs the address of p and writes a new address (the one you provide it) into that location.
For example, if p lives at 0x27, it means that reading memory location 0x27 yields the address of the object pointed to by p. So, if you use *p in the right hand side of an assignment, the steps to get the value of *p are:
Read the contents of 0x27 - say it's 0x80 - this is the value of the pointer, or, equivalently, the address of the pointed-to object
Read the contents of 0x80 - this finally gives you *p.
What if p is an array? If p is an array, then the variable p itself represents the array. By convention, the address representing an array is the address of its first element. If the compiler chooses to store the array in address 0x59, it means that the first element of p lives at 0x59. So when you read p[0] (or *p), the generated code is simpler: the compiler knows that the variable p is an array, and the address of an array is the address of the first element, so p[0] is the same as reading 0x59. Compare this to the case for which p is a pointer.
If you lie to the compiler, and tell it you have a pointer instead of an array, the compiler will (wrongly) generate code that does what I showed for the pointer case. You're basically telling it that 0x59 is not the address of an array, it's the address of a pointer. So, reading p[i] will cause it to use the pointer version:
Read the contents of 0x59 - note that, in reality, this is p[0]
Use that as an address, and read its contents.
So, what happens is that the compiler thinks that p[0] is an address, and will try to use it as such.
Why is this a corner case? Why don't I have to worry about this when passing arrays to functions?
Because what is really happening is that the compiler manages it for you. Yes, when you pass an array to a function, a pointer to the first element is passed, and inside the called function you have no way to know if it is a "real" array or a pointer. However, the address passed into the function is different depending on whether you're passing a real array or a pointer. If you're passing a real array, the pointer you get is the address of the first element of the array (in other words: the compiler immediately grabs the address associated to the array variable from the symbol table). If you're passing a pointer, the compiler passes the address that is stored in the address associated with that variable (and that variable happens to be the pointer), that is, it does exactly those 2 steps mentioned before for pointer-based access. Again, note that we're discussing the value of the pointer here. You must keep this separated from the address of the pointer itself (the address where the address of the pointed-to object is stored).
That's why you don't see a difference. In most situations, arrays are passed around as function arguments, and this rarely raises problems. But sometimes, with some corner cases (like yours), if you don't really know what is happening down there, well.. then it will be a wild ride.
Personal advice: read the book, it's totally worth it.
Why the following expression is not a (null pointer) runtime error?
typedef struct{
int a,b,c;
} st;
st obj={10,12,15};
st *ptr1=&obj;
st *ptr2=NULL;
printf("%d",*(int *)((char*)ptr1+(int)&ptr2->b));
Because you are performing pointer arithmetic on a NULL pointer which invokes undefined behavior - and that's not required to crash.
actually, in GNU C, &ptr2->b while st *ptr2=NULL; produce the data member 'b' 's byte offset in the struct, it is 4 here
Unfortunately, dereferencing a null pointer doesn't always crash! Sometimes it just happily moves ahead, accessing invalid memory!
You're probably seeing the output value '12'. What the compiler is doing when you dereference a pointer is adding an offset to get the address of member.
ints are typically 4 bytes long, so if ptr2 had an address of, say, 10, then ptr2->a must also be at address 10, ptr2->b must be at 14, and ptr2->c must be at address 18.
Since ptr2 is NULL, it's adding 4 to get to member b, and NULL+4=4. Then you're adding 4 to ptr1 and dereferencing that, which gets you ptr1's b member!
But this is not portable, and you shouldn't do this!
This is perfectly legal usage because the "take address of"-operator actually means: "Do not load/store the value of the variable, just give me the address you have computed to access it." It stops the access before the actual undefined behaviour is invoked.
This is such a typical idiom in programming that it was actually encapsulated in the offsetof() macro (which is used quite extensively in linux) and has since made its way into the compilers themselves to provide more meaningful error messages. See http://en.wikipedia.org/wiki/Offsetof for more details, even though I disagree with this article on the legality of the statement.
I've just started to learn C so please be kind.
From what I've read so far regarding pointers:
int * test1; //this is a pointer which is basically an address to the process
//memory and usually has the size of 2 bytes (not necessarily, I know)
float test2; //this is an actual value and usually has the size of 4 bytes,
//being of float type
test2 = 3.0; //this assigns 3 to `test2`
Now, what I don't completely understand:
*test1 = 3; //does this assign 3 at the address
//specified by `pointerValue`?
test1 = 3; //this says that the pointer is basically pointing
//at the 3rd byte in process memory,
//which is somehow useless, since anything could be there
&test1; //this I really don't get,
//is it the pointer to the pointer?
//Meaning, the address at which the pointer address is kept?
//Is it of any use?
Similarly:
*test2; //does this has any sense?
&test2; //is this the address at which the 'test2' value is found?
//If so, it's a pointer, which means that you can have pointers pointing
//both to the heap address space and stack address space.
//I ask because I've always been confused by people who speak about
//pointers only in the heap context.
Great question.
Your first block is correct. A pointer is a variable that holds the address of some data. The type of that pointer tells the code how to interpret the contents of the address being held by that pointer.
The construct:
*test1 = 3
Is called the deferencing of a pointer. That means, you can access the address that the pointer points to and read and write to it like a normal variable. Note:
int *test;
/*
* test is a pointer to an int - (int *)
* *test behaves like an int - (int)
*
* So you can thing of (*test) as a pesudo-variable which has the type 'int'
*/
The above is just a mnemonic device that I use.
It is rare that you ever assign a numeric value to a pointer... maybe if you're developing for a specific environment which has some 'well-known' memory addresses, but at your level, I wouldn't worry to much about that.
Using
*test2
would ultimately result in an error. You'd be trying to deference something that is not a pointer, so you're likely to get some kind of system error as who knows where it is pointing.
&test1 and &test2 are, indeed, pointers to test1 and test2.
Pointers to pointers are very useful and a search of pointer to a pointer will lead you to some resources that are way better than I am.
It looks like you've got the first part right.
An incidental thought: there are various conventions about where to put that * sign. I prefer mine nestled with the variable name, as in int *test1 while others prefer int* test1. I'm not sure how common it is to have it floating in the middle.
Another incidental thought: test2 = 3.0 assigns a floating-point 3 to test2. The same end could be achieved with test2=3, in which case the 3 is implicitly converted from an integer to a floating point number. The convention you have chosen is probably safer in terms of clarity, but is not strictly necessary.
Non-incidentals
*test1=3 does assign 3 to the address specified by test.
test1=3 is a line that has meaning, but which I consider meaningless. We do not know what is at memory location 3, if it is safe to touch it, or even if we are allowed to touch it.
That's why it's handy to use something like
int var=3;
int *pointy=&var;
*pointy=4;
//Now var==4.
The command &var returns the memory location of var and stores it in pointy so that we can later access it with *pointy.
But I could also do something like this:
int var[]={1,2,3};
int *pointy=&var;
int *offset=2;
*(pointy+offset)=4;
//Now var[2]==4.
And this is where you might legitimately see something like test1=3: pointers can be added and subtracted just like numbers, so you can store offsets like this.
&test1 is a pointer to a pointer, but that sounds kind of confusing to me. It's really the address in memory where the value of test1 is stored. And test1 just happens to store as its value the address of another variable. Once you start thinking of pointers in this way (address in memory, value stored there), they become easier to work with... or at least I think so.
I don't know if *test2 has "meaning", per se. In principle, it could have a use in that we might imagine that the * command will take the value of test2 to be some location in memory, and it will return the value it finds there. But since you define test2 as a float, it is difficult to predict where in memory we would end up, setting test2=3 will not move us to the third spot of anything (look up the IEEE754 specification to see why). But I would be surprised if a compiler would allow such thing.
Let's look at another quick example:
int var=3;
int pointy1=&var;
int pointy2=&pointy1;
*pointy1=4; //Now var==4
**pointy2=5; //Now var==5
So you see that you can chain pointers together like this, as many in a row as you'd like. This might show up if you had an array of pointers which was filled with the addresses of many structures you'd created from dynamic memory, and those structures contained pointers to dynamically allocated things themselves. When the time comes to use a pointer to a pointer, you'll probably know it. For now, don't worry too much about them.
First let's add some confusion: the word "pointer" can refer to either a variable (or object) with a pointer type, or an expression with the pointer type. In most cases, when people talk about "pointers" they mean pointer variables.
A pointer can (must) point to a thing (An "object" in standards parlance). It can only point to the right kind of thing; a pointer to int is not supposed to point to a float object. A pointer can also be NULL; in that case there is no thing to point to.
A pointertype is also a type, and a pointer object is also an object. So it is allowable to construct a pointer to pointer: the pointer-to-pointer just stores the addres of the pointer object.
What a pointer can not be:
It cannot point to a value: p = &4; is impossible. 4 is a literal value, which is not stored in an object, and thus has no address.
the same goes for expressions: p = &(1+4); is impossible, because the expression "1+4" does not have a location.
the same goes for return value p = &sin(pi); is impossible; the return value is not an object and thus has no address.
variables marked as "register" (almost distinct now) cannot have an address.
you cannot take the address of a bitfield, basically because these can be smaller than character (or have a finer granularity), hence it would be possible that different bitmasks would have the same address.
There are some "exceptions" to the above skeletton (void pointers, casting, pointing one element beyond an array object) but for clarity these should be seen as refinements/amendments, IMHO.