Hello Everybody,

I have a small confusion with regards to pointers. Here is some code

int main()
{
     int *p1 = (int*)malloc(sizeof(int));
     *p1 = 10;

     printf("The number is %d",*(char*)p1);
}

I run the code and the O/p is 10. My question is, is there no difference in using char typecast as opposed to an int typecast ?

In C language the return value from malloc() does not need to be typecast at all. But if you do use typecast then it needs to be typecast to the appropriate type. For example the line 3 you posted the return value of malloc could not be typecast as char* because that it the wrong type.

// it doesn't matter what's the pointer, you've requested the printf to treat it as an integer.
printf("The number is %d",*(char*)p1);
// You'll see the difference if you instead do this:
int main()
{
     int *p1 = (int*)malloc(sizeof(int));
     *p1 = 60;

     printf("The number is -%d-\n",*(char*)p1);
     printf("The char is -%c-\n",*(char*)p1);
     printf("The hex is -%x-\n",*(char*)p1);
     printf("The hex of ptr is -%x-\n", p1);

    return 0;
}

// OUTPUT IS
//
// The number is -60-
// The char is -<-
// The hex is -3c-
// The hex of ptr is -3e2bf8-
//

Casting (of parameter) doesn't really matter (i.e. you can cast anything to anything) as long as you confirm to the type expected by the function to which you pass the parameter.
What matters is how the function tries to interpret the parameter. If you pass an int with value "0" to a function expecting a pointer and the function tries to dereference it, it'll bomb because it tries to dereference 0x00000000.

Brightest example are malloc() / free(),
-- malloc() just reserves some chunk of memory for you, it's up to you to decide how to you want to use that memory. In case above you're using it as (int). But you have the option of using the same memory as a char or long (not wise as sizeof(long) > sizeof(int) ) or ...
-- If you cast the output of malloc() to int and pass it to free(), it'll tries to free sizeof(int) bytes. But if you cast it to char and pass the same address to free, it'll free sizeof(char) bytes, and so on..

Hope it's clear.

In C language the return value from malloc() does not need to be typecast at all. But if you do use typecast then it needs to be typecast to the appropriate type. For example the line 3 you posted the return value of malloc could not be typecast as char* because that it the wrong type.

Is it not "should not" instead of "could not"?

could not is correct -- meaning that if you did it then the compiler should probably produce an error for wrong typecast. (can not convert char* to int*, or something like that)

the return value of malloc could not be typecast as char* because that it the wrong type.

Confused as always. malloc returns void * , which of course can be typecasted to anything.

As for the original question:
I run the code and the O/p is 10.

Try to run it on a big-endian machine.

Confused as always. malloc returns void * , which of course can be typecasted to anything.

.

I didn't say void* can't be typecast to anything. I said it int* can't be typecast to char*. int* x = (char *)malloc(sizeof(int)); Please read and comprehend before you look like a fool.

Say what?

I said it int* can't be typecast to char*.

Care to elaborate?

See the code snippet I posted for clarification of what I meant. Of course int* can be typecast to char* under some circumstances. But not when typecasting the return value of malloc. Another place where such typecasts won't work correctly is line 6 of the original post in this thread. In that case its not a compiler error, but a logic error because, as someone already pointed out, printf() will be expecting an integer but only getting a char which will be upgraded to int when its passed to printf().

See the code snippet I posted for clarification of what I meant.

Now I am really confused. Which snippet?

But not when typecasting the return value of malloc.

Care to elaborate? (TM)

printf() will be expecting an integer but only getting a char

It will be getting int all right.The pointer is very well aligned. On a little-endian machine it would be a right int, surprisingly.

>>Now I am really confused. Which snippet? int* x = (char *)malloc(sizeof(int)); >>Care to elaborate? (TM)
Do I really need to explain what's wrong with the above code snippet? Put that line in a C program and try to compile it. VC++ 2010 Express gives warning: warning C4133: 'initializing' : incompatible types - from 'char *' to 'int *'

>>It will be getting int all right.The pointer is very well aligned. On a little-endian machine it would be a right int, surprisingly.
Not really a pointer problem. Try storing a large number in the integer (someing greater than 255) then see what you get. It takes 4 bytes (on 32-bit compilers) to store an integer. All that is being sent is one of those four bytes.

could not is correct -- meaning that if you did it then the compiler should probably produce an error for wrong typecast. (can not convert char* to int*, or something like that)

Mine didn't at least.. or is there some other option apart from -Wall that I should use?

[root@forssa kash]# cat <<EOF > a.c
> int main() {
>     int *pi = 0;
>     char *pc = (char *) pi;
>     long *pl1 = (long *) pi;
>     long *pl2 = (long *) pc;
>
>     return 0;
> }
>
> EOF
[root@forssa kash]# cc -Wall a.c
a.c: In function 'main':
a.c:6: warning: unused variable 'pl2'
a.c:5: warning: unused variable 'pl1'
[root@forssa kash]# 
[root@forssa kash]# cc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)
[root@forssa kash]#

The code you posted doesn't have any typcasting problems. Try this and see what gcc does: long* pl1 = (char *)p1; That's the kind of typcast problem I'm talking about.

try to compile it. VC++ 2010 Express gives warning

Sorry for annoyance. Is VC++ 2010 Express compliant?

Not really a pointer problem

I had an impression we're not talking pointers in general. Just pointers malloc returns.

PS:

don't know about gcc. its just a wierd compiler that doesn't complain about stuff that it should.

I have a strict policy to avoid smiley faces.

The code you posted doesn't have any typcasting problems. Try this and see what gcc does: long* pl1 = (char *)p1; That's the kind of typcast problem I'm talking about.

Aha..
If I may say, that would be stupid.. :)

>> Sorry for annoyance. Is VC++ 2010 Express compliant?
Yes. What compiler are you using?

>>I had an impression we're not talking pointers in general
That was referring to the printf() line, where the format specifer string uses %d yet only one of the 4 bytes of the integer is in the parameter list.

As for the malloc() line -- it had notthing to do with endianness.

Aha..
If I may say, that would be stupid.. :)

My point exactly.

>> Sorry for annoyance. Is VC++ 2010 Express compliant?
Yes. What compiler are you using?

None.

>>I had an impression we're not talking pointers in general
That was referring to the printf() line, where the format specifer string uses %d yet only one of the 4 bytes of the integer is in the parameter list.

Huh? this one?

printf("The number is %d",*(char*)p1);

there is a pointer passed there.

Really sorry. Quoting seem to be messed up. More questions to Dani.

>> Sorry for annoyance. Is VC++ 2010 Express compliant?

Yes. What compiler are you using?

None.

>>I had an impression we're not talking pointers in general
That was referring to the printf() line, where the format specifer string uses %d yet only one of the 4 bytes of the integer is in the parameter list.

Huh? this one?

printf("The number is %d",*(char*)p1);

there is a pointer passed there.

>>None.
That link doesn't work for me.

>>there is a pointer passed there.
The problem is not the pointer -- the problem is typecasting int* into char* when passting its value to printf(). int* is four bytes of memory, while char* is only one. So *(char*)p1 tells the compiler to pass only the first byte of that four-byte integer to printf(). It may actually seem to work when storing the value of 10 to the integer. But store the value of 123456 to the integer and see what you get.

> The problem is not the pointer

I suppose that now we are in the violent agreement.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.