int *p=123;
char *s="hi";
i tried searching this question on google but didn't get the exact answer.So, the question is why does the compiler throw error when we assign numbers in the place of the address to an integer pointer, But compiles perfectly when a char pointer is assigned string or bunch of characters and stores them in the memory with each character by different memory address.
like the code i have put in the beginning, when i declare the int pointer and assign it the integers it throws the warning "warning: initialization of 'int *' from 'int' makes pointer from integer without a cast" but when i declare the char pointer and not assign it the address but the characters, it compiles without a problem. As the char pointer stores each character with its own address in the memory, shouldn't the int pointer store each number in the memory as an array with each element's different address?
CodePudding user response:
C 2018 6.5.16.1 1 specifies constraints for assignments. The first constraint about assigning to a pointer is:
— the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;
In int *p=123;, p is initialized, not assigned. However, the rules for initialization say the rules for assignment apply, in 6.7.9 11. p is a pointer, but 123 is an int, not a pointer, so it does not satisfy the constraint, and the compiler complains.
In char *s="hi";, "hi" is an array of characters. It is used as an expression to provide the initial value of s. C automatically converts an array used as an expression to a pointer to its first element.1 Thus, with "hi", we have a pointer to a character, which is a char *, and the constraint above allows assigning a char * to a char *, so the compiler does not complain.
Note that p = 123; would not assign the address of 123 to the pointer. It would attempt to assign the value of 123 to the pointer. That should never be done except in special situations where a special memory address is known, such as an address for a hardware interface or a special address set by the operating system. In those cases, we would use a cast to convert the integer address to a pointer, as with p = (void *) 0x1000;. In contrast, the reason s = "hi"; assigns the address of "hi" to s instead of assigning its value is because of the automatic conversion of an array to a pointer.
For completeness, the second constraint about assigning to a pointer is:
— the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) one operand is a pointer to an object type, and the other is a pointer to a qualified or unqualified version of
void, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;
This does not apply since there is no void * involved.
The third constraint about assigning to a pointer is:
— the left operand is an atomic, qualified, or unqualified pointer, and the right is a null pointer constant; or
This rule would allow you to assign an integer to a pointer, because one kind of null pointer constant is an integer constant expression with value 0. Thus, int *p = 0; or int *p = 4-4; is allowed. int *p = x-x; would not satisfy this constraint because it is not a constant expression.
Footnote
1 This conversion is not performed when the array is the operand of sizeof, is the operand of unary &, or is a string literal used to initialize an array. The rule for this is in 6.3.2.1 3.
CodePudding user response:
First of all, you are trying to store a primitive type to a pointer. Since pointers expect pointers either a variable address or an array starting point, they cannot really hold a variable directly.
When you declared the variable "hi" this way: char *s = "hi";, you actually created an array of characters which is stored in stack segment if it is not global. However, when you tried to store 123, it is a primitive type as I mentioned, so you are trying to store a variable to the pointer which expects address.
If you try to do something like, char s1[3] = {'h', 'i', '\0'}; this will work similarly with the "hi" declaration. What you did with your code is like char* s = 'h' which will give an error as well.
As a result, pointers need to store addresses, so that primitive types cannot be used at right side of the assigning.
