Reputation: 91
I'm new to C and have a trouble understanding pointers. The part that I'm confused is about char *
and int *
.
For example, we can directly assign a pointer for char, like
char *c = "c";
and it doesn't make errors.
However, if I assign a pointer for int like I just did, for example int * a = 10;
,
it makes errors. I need to make an additional space in memory to assign a pointer for int,
like int *b = malloc(sizeof(int)); *b = 20; free(b);
...
Can anyone tell me why?
Upvotes: 5
Views: 1568
Reputation: 954
The direct answer to your question, is that, C
language is a strict typed language. And before the machine code is produced, a compiler checks for some possible errors. The types are different, and that is all that the compiler wants to know.
But from the bit-byte point of view, there are no difference, for C
language, with the above two pointers.
Take a look at your code with online compiler
void main(){
int * a = 10; /* <= this presumably gives you an error. */
}
What I did is copy pasted your code that gives you the error. And online compiler had emitted a warning, not an error. Even more than that. Change the C
standard to be of c17
and you still get a mere warning.
The note about assigning a string literal to a pointer had been discussed broadly at SO. It deserves a different topic.
To sum it up. For the C
language there is no meaningful difference in the above two pointers. It is a user, who takes a responsibility to know a layout of a memory in his/her program. All in all, the language was designed as a high level tool that operates over linear memory.
Upvotes: -1
Reputation: 134066
In initialization the right-hand side (RHS) expression must be of or convertible to the type of the variable declared.
If you do
char *cp = ...
int *ip = ...
then what is in ...
must be convertible to a pointer to a char
or a pointer to an int
. Also remember that a char
is a single character.
Now, "abc"
is special syntax in C - a string literal, for creating an array of (many) immutable characters. It has the type char [size]
where size
is the number of characters in the literal plus one for the terminating null character. So "c"
has type char [2]
. It is not char
. An array in C is implicitly converted to pointer to the first element, having then the type "pointer to the element type". I.e. "c"
of type char [2]
in char *cp = "c";
is implicitly converted to type char *
, which points to the first of the two characters c
and \0
in the two-character array. It is also handily of type char *
and now we have char *cp = (something that has type char * after conversions);
.
As for int *
, you're trying to pass an integer value to a pointer. It does not make sense.
A pointer holds an address. If you'd ask for the address of Sherlock Holmes, the answer would be 221 Baker Street. Now instead what you've done is "address of Sherlock Holmes is this photo I took of him in this morning".
The same incorrect code written for char *
would be
char *cp = 'c'; // or more precisely `char *p = (char)'c';
and it would give you precisely the same error proving that char *cp
and int *cp
work alike.
Unfortunately C does not have int
string literals nor literals for integer arrays, though from C99 onwards you could write:
int *ip = (int[]){ 5 };
or
const int *ip = (const int[]){ 5 };
Likewise you can always point a char *
or int *
to a single object of that type:
char a = 'c'; char *pa = &a; int b = 42; int *pb = &b;
now we can say that a
and *pa
designate the same char
object a
, and likewise b
and *pb
designate the same int
object b
. If you change *pa
you will change a
and vice versa; and likewise for b
and *pb
.
Upvotes: 4
Reputation: 123598
A string literal like "c"
is actually an array expression (the type of "c"
is "2-element array of char
).
Unless it is the operand of the sizeof
or &
operators, or is a string literal used to initialize a character array in a declaration, an expression of type "array of T
" will be converted, or "decay" to an expression of type "pointer to T
" and its value will be the address of the first element of the array.
So when you write
char *c = "c";
it’s roughly equivalent to writing
char string[] = "c";
char *c = &string[0];
You’re assigning a pointer to a pointer, so the compiler doesn’t complain.
However, when you write
int *a = 10;
you’re assigning an int
value to a pointer and the types are not compatible, so the compiler complains. Pointers are not integers; they may have an integer representation, but that’s not guaranteed, and it won’t be the same size as int
.
Upvotes: 2
Reputation: 1765
Are there differences between int pointer and char pointer in c?
All pointers in C are created equal in the last decades. During some time there were pointers of different sizes, in some platforms like Windows, due to a thing called memory model.
Today the compiler sets the code to use 32-bit or 64 or any size pointers depending on the platform, but once set all pointers are equal.
What is not equal is the thing a pointer points to, and it is that you are confused about.
void*
pointer. malloc()
allocates memory in C. It always return a void*
pointer and you then cast it to anything you needsizeof(void*)
is the same as sizeof(int*)
. And is the same as sizeof(GiantStruct*)
and in a 64-bit compiler is 8 bytes or 64 bits"c"
. is is char[2]
. And it is a string literal. Somewhere in memory the system will allocate an area of at least 2 bytes, put a 'c'
and a zero there, since string literals are NULL
terminated in C
, take that address in put in the address allocated to your pointer c
.int* a = 10
?a
? a is int*
pointer to an int
. And what is *a
? an int
. At which address? 10
. Well, truth is the system will not let you access that address just because you set a pointer to point to it. In the '80s you could. Today there are very strong rules on this: you can only access memory allocated to your processes. Only. So the system aborts your program as soon as you try to access.if you write
int* a = malloc(300);
the system will allocate a 300-bytes area, take the area address and write it for you at the address allocated to a. When you write *a=3456
the system will write this value to the first sizeof(int)
bytes at that address.
You can for sure write over all 300, but you must somewhat manipulate the pointer to point inside the area. Only inside that area. In fact C language was designed just for that.
Let us write "c" to the end of that 300-byte area alocated to a:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* c = "c";
int* a = (int*)malloc(300);
*a = 3456;
printf("Area content is %d\n", *a);
char* pToEnd = (char*)a + 298;
*(pToEnd) = 'c';
*(pToEnd + 1) = 0;
printf("At the end of the 300-byte area? [Should be 'c'] '%s'\n", pToEnd);
printf("The pointer c points to '%s'\n", c);
//*c = 'x'; // error: cancel program
c = pToEnd;
printf("The pointer c now points do the end of the 300-byte area:'%s'\n", c);
free(a);
return 0;
};
and see
Area content is 3456
At the end of the 300-byte area? [Should be 'c'] 'c'
The pointer c points to 'c'
The pointer c now points do the end of the 300-byte area:'c'
Also note that as soon as you try to write over c
, the char
pointer in your example, your program will also cancel. It is a read only area --- see the comment on line 14. But you can point c
inside the area in the example and use it, since the pointer in itself is not constant.
And when you write c = pToEnd
in the example above access to the string literal is lost forever. In some sense is a memory leak, but it is a static allocated area. The leak is not the area but the address.
Note also that free(a)
at the end, even if being a
int*
will free all 300 bytes
Upvotes: 0
Reputation: 211740
I think you're misunderstanding what a pointer is and what it means. In this case:
int* a = 10;
You're saying "create a pointer (to an int
) and aim it at the literal memory location 0x0000000A
(10).
That's not the same as this:
int n = 10;
int* a = &n;
Which is "create a pointer (to an int
) and aim it at the memory location of n
.
If you want to dynamically allocate this:
int* a = malloc(sizeof(int));
*a = 10;
Which translates to "create a pointer (to an int
) and aim it at the block of memory just allocated, then assign to that location the value 10
.
Normally you'd never allocate a single int
, you'd allocate a bunch of them for an array, in which case you'd refer to it as a[0]
through a[n-1]
for an array of size n
. In C *(x + y)
is generally the same as x[y]
or in other words *(x + 0)
is either just *x
or x[0]
.
Upvotes: 6
Reputation: 731
In your example, you do not send c
to the char 'c'
. You used "c"
which is a string-literal.
For string-literals it works as explained in https://stackoverflow.com/a/12795948/5280183.
Upvotes: 3