Junyoung
Junyoung

Reputation: 91

Are there differences between int pointer and char pointer in c?

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

Answers (6)

user14063792468
user14063792468

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

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

John Bode
John Bode

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

arfneto
arfneto

Reputation: 1765

Are there differences between int pointer and char pointer in c?

short answer: NO

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.

  • consider a void* pointer. malloc() allocates memory in C. It always return a void* pointer and you then cast it to anything you need
  • sizeof(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

what about char* c = "c"?

  • you must ask yourself what is "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.

what about int* a = 10?

  • it is the same thing. It is somewhat ok until the operating system comes in. What is 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.

an example

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

tadman
tadman

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

andrbrue
andrbrue

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

Related Questions