简体   繁体   中英

What is the difference between int* and char* when using malloc() to allocate the same size of memory

int* pInt = malloc(512);
char* pChar = malloc(512);

I have a hard time to grasp the concept. Pointer type has the same size, 4 or 8 bytes, depending on the system. int has 4 bytes, and char has 1 byte. Here, I am allocating 512 bytes to each pointer of type int and char. Those pointers should have the same size (block of memory). I understand that they point to different blocks of memory which both have 512 bytes. BUT how are they different?

They both point to 512-byte blocks of memory. There are really only two differences:

1) When you dereference them, pInt will store and load integer values while pChar will store and load character values.

2) pInt[1] will refer to the second integer sized chunk of the block of memory pInt points to. pChar[1] will refer to the second character-sized chunk of the block of memory pChar points to.

So:

*pInt = 0; Sets to the integer value zero the first integer-sized chunk of memory in the block pInt points to.

*pChar = 0; Sets to the character value zero the first character-sized chunk of memory in the block pChar points to.

You're right. pInt and pChar are pretty similar. (If you look at the emitted machine code, they're probably identical -- so far.)

The difference comes when you use the pointers. When you say

*pChar = 0;

you'll set 1 byte pointed to by pChar to 0. But when you say

*pInt = 0;

you'll set a whole int's worth of memory to 0.

Both statements are assignment expressions. An assignment has two sides: the left one, that denotes to whom a value is assigned and the right one, that denotes the value to assign.

In your example the right side reserves the memory: malloc(512) . Doing so, nothing is said about the usage of that block, esp. nothing is said about what type of data there is stored. In both cases malloc(512) do exactly the same. There is no difference. Memory blocks reserved by malloc() never has a type out of themselves.

malloc() returns a pointer to the memory block. Since it has no idea about the data stored there this is a void-pointer, an "untyped" pointer. Assigning this to a typed pointer, will have effects:

First of all you bring semantics into it. Nobody can say, what kind of data is stored in the block whose address is returned by malloc() . When you assign it to an int pointer, it says: "There are ints stored in that block." Analogue with char pointers.

Second, you tell the compiler something about the data stored there, when you do operation with it: I. e. if you store a value into the memory block using a char pointer as pChar , only one byte of the block will be affected. This is, because chars have the size of one byte by definition.

If you store a value into the memory block using an int pointer as pInt , 4 or 8 (or whatever on your machine) are affected.

But this depends on the way you refer the memory block, the type of the pointer. The memory block itself is still typeless. Therefore you can change the type:

int* pInt = malloc(512); // A typeless memory block referred by an int pointer
*pInt = 4; // Will affect 4 (or 8 or whatever) bytes
char* pChar = (char*)pInt; // A char pointer referring *the same* typeless memory block
*pChar = 'M'; // Will affect one byte

So, the memory block does not have any type. The pointer to memory inside the memory block gives a type to the access to the block. The block itself is stilled typeless.

int *pInt = malloc(512) is similar to int pInt[128];

char *pChar = malloc(512) is similar to char pChar[512];

Note ints are 4 bytes large and 512 / 4 = 128. (Sometimes ints are not 4 bytes large. It depends on the compiler.)

The blocks themselves are not different. Rather, their differing types affect how the compiler treats those blocks of memory. The compiler does not allow you to freely switch between types , but you can do so anyways through typecasting , ie (char *)pInt; for example.

Below is some code that manipulates pInt and pChar to demonstrate their relationship. Note the use of typecasting to avoid compiler errors.

#include <stdio.h>
#include <stdlib.h>

static const int BLOCKSIZE = 8;

void print_as_chars(char *print_me)
{
    int i;
    for (i = 0; i < BLOCKSIZE; ++i)
    {
        printf ("%4d ", print_me[i]);
    }
    printf ("\n");
}

void print_as_ints(int *print_me)
{
    int i;
    for (i = 0; i < BLOCKSIZE / sizeof(int); ++i)
    {
        printf ("%19d ", print_me[i]);
    }
    printf("\n");
}

int main (void)
{
    int *pInt = malloc(BLOCKSIZE);
    char *pChar = malloc(BLOCKSIZE);

    // We can set any value in pInt
    pInt[0] = 25;
    pInt[1] = 300;

    // But represent the memory in any way we want.
    printf ("pInt:\n");
    print_as_ints(pInt); // 25 300
    print_as_chars((char *)pInt); // 0 0 0 25 0 0 1 44
    printf ("\n");

    // It works both ways!
    pChar[0] = 0; pChar[1] = 0; pChar[2] = 0; pChar[3] = 25;
    pChar[4] = 0; pChar[5] = 0; pChar[6] = 1; pChar[7] = 44;

    printf ("pChar:\n");
    print_as_ints((int *)pChar); // 25 300
    print_as_chars(pChar); // 0 0 0 25 0 0 1 44
    printf ("\n");

    return 0;
}

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