In this statement
printf("%d\n %d\n", *ptr, *intptr);
there are outputted not the pointers themselves but the data they point to.
For example 300 can be represented like 256 + 44. So 44 can be stored in one byte while 256 can be stored in another byte.  And this expression *ptr gives the value 44 stored in the byte pointed to by the pointer ptr.
On the other hand the pointer intptr points to the whole object of the type int and the expression *intptr  gives the value 300.
If you want to output the addresses stored in the pointers you should write
printf("%p\n %p\n", ( void * )ptr, ( void * )intptr);
To output sizes of the pointers you could write
printf("%zu\n %zu\n", sizeof( ptr ), sizeof( intptr ));
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )
Also in this declaration you should use an explicit casting
char *ptr = ( char * )&a;
Here is a demonstrative program
#include <stdio.h>
int main(void) 
{
    int a = 300;
    char *ptr = ( char * )&a;
    int *intptr = &a;
    printf( "*ptr = %d, *intptr = %d\n", *ptr, *intptr );
    printf( "ptr = %p, intptr = %p\n", ( void * )ptr, ( void * )intptr );
    printf( "sizeof( ptr ) = %zu, sizeof( intptr ) = %zu\n", 
        sizeof( ptr ), sizeof( intptr ) );
    return 0;
}
Its output might look like
*ptr = 44, *intptr = 300
ptr = 0x7ffe5972613c, intptr = 0x7ffe5972613c
sizeof( ptr ) = 8, sizeof( intptr ) = 8