Home > Net >  Why char pointer increments by one byte though its size is 8?
Why char pointer increments by one byte though its size is 8?

Time:07-30

void main() {
    char var = 10;
    char *ptr = &var;
    
    printf("Pointer address before increment:%p\n", ptr);
    printf("sizeof(ptr):%d\n", sizeof(ptr));
    ptr  ;
    printf("Pointer address after increment:%p\n", ptr);
    printf("sizeof(ptr):%d\n", sizeof(ptr));
}

Output:

Pointer address before increment:0x7fffb997144f
sizeof(ptr):8
Pointer address after increment:0x7fffb9971450
sizeof(ptr):8

Why does the char pointer increment by one byte only? Its size is 8, right? When ptr is declared, the compiler allocates 8 bytes to it. When we increment it by 1, it increments based on the datatype. Why? How does this works?

CodePudding user response:

For starters to output values of the type size_t you need to use the conversion specifier zu instead of d

printf("sizeof(ptr):%zu\n",sizeof(ptr));
                    ^^^

Incremented pointer points to the memory after the object it points to. That is the value of a pointer of the type T * is incremented by the value sizeof( T ).

Consider for example accessing array elements.

T a[N];

The expression a[i] evaluates like ( a i ). So the value of the pointer is incremented by i * sizeof( T ).

This is called the pointer arithmetic,

As for the size of objects of the type char then according to the C Standard sizeof( char ) is always equal to 1.

Also consider the following demonstration program.

#include <stdio.h>

int main( void )
{
    char s[] = "Hello";

    for ( const char *p = s; *p != '\0';   p )
    {
        putchar( *p );
    }
    putchar( '\n' );
}

Its output is

Hello

If the pointer p was incremented by the value sizeof( char * ) then you could not output the array using the pointer.

CodePudding user response:

For pointer arithmetics, what matters is not the sizeof the pointer, but the size of the type it points to:

  • T a[10]; T *p = a; defines a pointer p to an array of objects of type T.
  • p contains the memory address of the first element of a.
  • The next element's address is sizeof(T) bytes farther, so incrementing the pointer p by 1 increments the memory address by sizeof(*p).

Here is a modified version:

#include <stdio.h>

int main() {
    char char_array[2] = "a";
    char *char_ptr = char_array;
    
    printf("sizeof(char_ptr): %zu\n", sizeof(char_ptr));
    printf("char_ptr before increment: %p\n", (void *)char_ptr);
    printf("sizeof(*char_ptr): %zu\n", sizeof(*char_ptr));
    char_ptr  ;
    printf("char_ptr after increment: %p\n", (void *)char_ptr);

    int int_array[2] = { 1, 2 };
    int *int_ptr = int_array;
    
    printf("\nsizeof(int_ptr): %zu\n", sizeof(int_ptr));
    printf("int_ptr before increment: %p\n", (void *)int_ptr);
    printf("sizeof(*int_ptr): %zu\n", sizeof(*int_ptr));
    int_ptr  ;
    printf("int_ptr after increment: %p\n", (void *)int_ptr);

    return 0;
}

Output (64 bits):

sizeof(char_ptr): 8
char_ptr before increment: 0x7fff52c1f7ce
sizeof(*char_ptr): 1
char_ptr after increment: 0x7fff52c1f7cf

sizeof(int_ptr): 8
int_ptr before increment: 0x7fff52c1f7c0
sizeof(*int_ptr): 4
int_ptr after increment: 0x7fff52c1f7c4

Output (32 bits):

sizeof(char_ptr): 4
char_ptr before increment: 0xbffc492e
sizeof(*char_ptr): 1
char_ptr after increment: 0xbffc492f

sizeof(int_ptr): 4
int_ptr before increment: 0xbffc4930
sizeof(*int_ptr): 4
int_ptr after increment: 0xbffc4934

CodePudding user response:

That's because a charactor occupies 1 byte, while a pointer to charactor is a pointer, not a charactor or something else, that means it stored a memory adress, so it occupies 8 bytes. Also all kinds of pointer is 8 bytes on your machine.

CodePudding user response:

What are pointers?

Briefly the pointers are a special types of variables for holding memory addresses and its bit wide or byte size that the compilers allocate may vary depending on the platform. If you size a pointer using the sizeof operator in an 8-bit architecture for example, in most devices you will get 2 bytes, that is, a pointer can hold an address value up to 64kB. This is logically big enough to hold address value for devices that only has up to 64kB of ROM and up to a few kBs of RAM.

Since the architecture in which you compile your code is a 64-bit architecture, the system registers are 64-bits wide and it's wide enough to hold very large address values (2 * 10^64). Since its big enough it will naturally size 64-bits / 8 bytes.

As said the pointers are special objects, so you cannot assign kinds of constants like

int* ptr = 0x7fffb997144f; // Compilers will not allow this

Compilers will not allow this because the pointers are not regular kind of variables. So in order to assign a constant address value you must cast it as pointer like in the following example:

int* ptr = (int*) 0x7fffb997144f; // Compilers will allow this

How the pointers are incremented

It depends on the byte size of the type to which a pointer points. That is;

  • 1 for char types
  • 2 for short int types
  • 4 for long types
  • 8 for long long types

Some type sizes like of int and float types may vary depending on the platform.

Now that we know about pointers and how it is incremented let's make an example for each type above. Let's assume that the start address for each example is 0x7fffb997144f.

  1. For char types
char vars[5];
char* ptr = vars;   // 0x7fffb997144f
ptr  ;              // 0x7fffb9971450
ptr  ;              // 0x7fffb9971451
  1. For short int types
short int vars[5];
short int* ptr = vars;  // 0x7fffb997144f
ptr  ;              // 0x7fffb9971451
ptr  ;              // 0x7fffb9971453
  1. For long types
long vars[5];
long* ptr = vars;   // 0x7fffb997144f
ptr  ;              // 0x7fffb9971454
ptr  ;              // 0x7fffb9971458
  1. For long long types
long long vars[5];
long long* ptr = vars;  // 0x7fffb997144f
ptr  ;              // 0x7fffb9971458
ptr  ;              // 0x7fffb997145f
  • Related