cast from int** to int*

P

Praveen Raj

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

int fun(int *p)
{
((int*)(*p))= (int*)malloc(sizeof(int));//casting int* to int**
return 0;
}

int main()
{
int *p=NULL;
fun(&p);//casting int** to int*
*p=10;
printf("%d",*p);
return 0;
}

in this program, casting int** to int* is valid or not??
and same for casting int* back to int**??
 
M

Mark Bluemel

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

int fun(int *p)
{
((int*)(*p))= (int*)malloc(sizeof(int));//casting int* to int**

"((int*)(*p))" is not an lvalue and can't be assigned.

Oh - and whatever you think you are doing, you're not casting here...
return 0;

}

int main()
{
int *p=NULL;
fun(&p);//casting int** to int*

Nor are you casting here. You declared fun as taking an int*, and you
actually pass int**.
*p=10;
printf("%d",*p);
return 0;

}

in this program, casting int** to int* is valid or not??
and same for casting int* back to int**??

What did your compiler tell you?
 
P

Praveen Raj

"((int*)(*p))" is not an lvalue and can't be assigned.

Oh - and whatever you think you are doing, you're not casting here...
In C, implicit cast is there.
Nor are you casting here. You declared fun as taking an int*, and you
actually pass int**.
implicit cast here too. leaving compiler to cast int** to int*
What did your compiler tell you?

compiling with gcc, it issues a two waring and can run the code fine.
 
P

Praveen Raj

Warning shown as:

temp_c\main.c||In function `fun':|
temp_c\main.c|6|warning: use of cast expressions as lvalues is
deprecated|
temp_c\main.c||In function `main':|
temp_c\main.c|13|warning: passing arg 1 of `fun' from incompatible
pointer type|
||=== Build finished: 0 errors, 2 warnings ===|
 
M

Morris Keesan

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

int fun(int *p) Should be int fun (int **p)
{
((int*)(*p))= (int*)malloc(sizeof(int));//casting int* to int**
This is not legal -- the result of a cast operator is not allowed on
the left-hand side of an assignment operator. If you insist on using
a cast here, the left-hand side would be *((int **)p), which is not
at all portable, but which would probably work on many architectures,
where (int) and (int *) have the same size and all pointers have the
same representation. But really, you don't need any cast here at all:
*p = malloc(sizeof(int));
return 0;
Why are you returning a value here? Why not just declare fun as returning
void? If you're returning a constant, then the return value carries no
information at all (and in fact, you're not even examining the return value
in the caller, so why bother?).
}

int main()
{
int *p=NULL;
fun(&p);//casting int** to int*
In spite of the comment, there's no cast happening. You're simply
passing an (int **) to a function which is expecting to receive an (int *)
and here you use *p without checking whether the
printf("%d",*p);
return 0;
}

in this program, casting int** to int* is valid or not??
and same for casting int* back to int**??

No, no, and no. In general, the presence of casts is a strong
indication that something is suspect in the code, and here it's clear
that you don't really understand what you're doing. If you're passing
an (int *) by reference to a function which is expected to modify that
(int *), as you do in the line "fun(&p)", then the function which is
receiving that argument should be declared as taking a parameter whose
type matches that argument, i.e.

fun(int **p)
{
*p = malloc(sizeof(int));
}
 
B

Ben Bacarisse

Praveen Raj said:
#include<stdio.h>
#include<stdlib.h>

int fun(int *p)
{
((int*)(*p))= (int*)malloc(sizeof(int));//casting int* to int**

This is not valid C. The main problem is that you can't have a cast
expression as the target of an assignment.
return 0;
}

int main()
{
int *p=NULL;
fun(&p);//casting int** to int*
*p=10;
printf("%d",*p);
return 0;
}

in this program, casting int** to int* is valid or not??
and same for casting int* back to int**??

It is not a good idea to reply on things like this. Why would you
want to do that? You seem to want this program:


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

void fun(int **p)
{
*p = malloc(sizeof **p);
}

int main(void)
{
int *p;
fun(&p);
*p = 10;
printf("%d\n", *p);
free(p);
return 0;
}

which is well-defined and portable. Is that what you wanted to do?
 
P

Praveen Raj

This is not valid C.  The main problem is that you can't have a cast
expression as the target of an assignment.




It is not a good idea to reply on things like this.  Why would you
want to do that?  You seem to want this program:

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

  void fun(int **p)
  {
       *p = malloc(sizeof **p);
  }

  int main(void)
  {
       int *p;
       fun(&p);
       *p = 10;
       printf("%d\n", *p);
       free(p);
       return 0;
  }

which is well-defined and portable.  Is that what you wanted to do?

I know this is portable but this was to illustrate the problem..
i dont want this..
 
B

Barry Schwarz

In C, implicit cast is there.

There is no such thing as an implicit cast. A cast is an operator,
just like & or +, and must be explicitly coded. There are implicit
conversions in C but not in this statement. Furthermore, there is no
int** in that statement, not in the text and not in the type of any of
the expressions.
 
B

Barry Schwarz

Warning shown as:

temp_c\main.c||In function `fun':|
temp_c\main.c|6|warning: use of cast expressions as lvalues is
deprecated|
temp_c\main.c||In function `main':|
temp_c\main.c|13|warning: passing arg 1 of `fun' from incompatible
pointer type|

The first diagnostic describes an extension provided by your compiler
that is not part of the language.

The second describes a constraint violation and is mandatory.
 
B

Barry Schwarz

On Fri, 3 Jul 2009 07:53:23 -0700 (PDT), Praveen Raj

snip code which does not demonstrate the issue in question.
in this program, casting int** to int* is valid or not??
and same for casting int* back to int**??

Neither conversion is portable. There is no guarantee that a value of
one type can be represented by the value of the other type.
Furthermore, if the value after conversion is misaligned, the behavior
is undefined.
 
P

Praveen Raj

Should be int fun (int **p)> {

This is not legal -- the result of a cast operator is not allowed on
the left-hand side of an assignment operator.
 If you insist on using
a cast here, the left-hand side would be   *((int **)p),

okay, this is good.
which is not
at all portable, but which would probably work on many architectures,
where (int) and (int *) have the same size and all pointers have the
same representation.  But really, you don't need any cast here at all:
     *p = malloc(sizeof(int));> return 0;

Why are you returning a value here?  Why not just declare fun as returning
void?  If you're returning a constant, then the return value carries no
information at all (and in fact, you're not even examining the return value
in the caller, so why bother?).> }

the return type is of no concern here..
In spite of the comment, there's no cast happening.  You're simply
passing an (int **) to a function which is expecting to receive an (int *)> *p=10;

I'm passing int** to int*, but int** is casted to int* implicitly to
store in int*;
and i know that is not portable.

what does standard say about a cast from int** to int*???
 
P

Praveen Raj

while calling fun(&p); doesn't a cast is made to store the int** to
int* as declared in the prototype..??
 
B

Ben Bacarisse

Praveen Raj said:
On Jul 3, 8:54 am, Ben Bacarisse <[email protected]> wrote:

It's best to snip sig blocks.
I know this is portable but this was to illustrate the problem..
i dont want this..

Without any parameters, it is hard for anyone suggest what to do. You
say your code compiles (my gcc does not generate an executable from
your code) and "works" but it is not standard C. Maybe that is OK
with you. If so, you have a solution.

I (and others) have posted a portable alternative but you say you
don't want that. Why not? How much undefined and implementation
defined behaviour are you prepared to accept? Why can't you have a
fully portable solution?
 
P

Praveen Raj

It's best to snip sig blocks.


Without any parameters, it is hard for anyone suggest what to do.  You
say your code compiles (my gcc does not generate an executable from
your code) and "works" but it is not standard C.  Maybe that is OK
with you.  If so, you have a solution.

I (and others) have posted a portable alternative but you say you
don't want that.  Why not?  How much undefined and implementation
defined behaviour are you prepared to accept?  Why can't you have a
fully portable solution?

Because the prototype of fun() is not allowed to change.

int fun(int *p);

and memory for the pointer p is to be allocated in function fun.
so i need to cast it and do all the things other way around..
 
B

Ben Bacarisse

Praveen Raj said:
okay, this is good.

Not really. Note "if you insist..." -- why must the type p be
changed? If you don't know the type, void * is the correct one to
use, not int *.

I'm passing int** to int*, but int** is casted to int* implicitly to
store in int*;
and i know that is not portable.

It is much clearer to say "converted" rather than "cast" ("casted" is
not grammatical). There is no cast in the code above and using the
term just confuses the matter.

However, there is no defined conversion from int ** to int *. The
fact that gcc is letting it go, after telling you about the problem,
does not mean that it will work in any other compiler. As written,
the line is a "constraint violation" (the closest the C standard comes
to saying "illegal") and a compiler is permitted to stop right there.
If you do put in a cast:

fun((int *)&p);

then the code is no longer a constraint violation.
what does standard say about a cast from int** to int*???

It says it is "implementation defined". You need to see what the
compiler says about it. Without the cast (as you originally wrote it)
it is not an implementation defined conversion -- it is a constraint
violation.

The code with and without a cast is different. It really is confusing
to call the conversion a cast here because it matters.

<snip>
 
P

Praveen Raj

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

int fun(int *p)
{
*(int**)(p)= malloc(sizeof(int));
return 0;
}

int main()
{
int *p=NULL;
fun((int*)&p);//i hope now i'm casting int** to int*
*p=10;
printf("%d",*p);
return 0;
}


now can i do this..??
or any portable way without changing the prototype of the fun();
 
B

Ben Bacarisse

Praveen Raj said:
#include<stdio.h>
#include<stdlib.h>

int fun(int *p)
{
*(int**)(p)= malloc(sizeof(int));
return 0;
}

int main()
{
int *p=NULL;
fun((int*)&p);//i hope now i'm casting int** to int*
*p=10;
printf("%d",*p);
return 0;
}


now can i do this..??

Yes, provided that you are prepared to accept implementation-defined
behaviour.
or any portable way without changing the prototype of the fun();

It could be argued that writing:

fun((void *)&p);

and

int fun(int *p)
{
int **ipp = (void *)p;
*ipp = malloc(sizeof **ipp);
return 0;
}

is slightly better defined, but I think the arguments would be largely
legalistic ones.

[Legalistic point: whilst the conversion from any object pointer to
void * and back is well-defined, the conversion is not obviously
well-defined when another type is involved, as here.]
 
K

Keith Thompson

Praveen Raj said:
Praveen Raj said:
On Jul 3, 8:54 am, Ben Bacarisse <[email protected]> wrote:

which is well-defined and portable.  Is that what you wanted to do?
[...]
I know this is portable but this was to illustrate the problem..
i dont want this..

Without any parameters, it is hard for anyone suggest what to do.  You
say your code compiles (my gcc does not generate an executable from
your code) and "works" but it is not standard C.  Maybe that is OK
with you.  If so, you have a solution.

I (and others) have posted a portable alternative but you say you
don't want that.  Why not?  How much undefined and implementation
defined behaviour are you prepared to accept?  Why can't you have a
fully portable solution?

Because the prototype of fun() is not allowed to change.

int fun(int *p);

and memory for the pointer p is to be allocated in function fun.
so i need to cast it and do all the things other way around..

Why is the prototype of fun() not allowed to change?

It looks like you're either using the wrong function for whatever it
is you're trying to do, or using the write function but using it
incorrectly. You haven't given us enough information to help you any
further than that.

Conversions between int* and int** are not guaranteed to work as you
might expect them to, and are almost never the right solution
to the problem.

So what *is* the problem? What exactly are you trying to accomplish?
 
M

Morris Keesan

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

int fun(int *p)
{
*(int**)(p)= malloc(sizeof(int));
return 0;
}

int main()
{
int *p=NULL;
fun((int*)&p);//i hope now i'm casting int** to int*
*p=10;
printf("%d",*p);
return 0;
}


now can i do this..??

Yes. On most platforms, it will probably work fine. But it's not
guaranteed to be work, because there's no requirement in the language
that (int *) and (int **) are compatible. I.e. there could be a
conforming implementation in which converting an (int **) to (int *)
and then back again could give you a changed value.

In practical terms, I don't think this will be a problem. I've worked on
a wide variety of hardware and software platforms, including some in which
(char *) was twice as large as (int *), or where pointers to functions
were totally incompatible with pointers to data, and I don't think I've
ever encountered a machine where pointer-to-pointer had a different
representation from pointer-to-int. But if you wanted to make the code
more robust, you could add code like this somewhere

int *ip;
int **ipp;
ipp = &ip;

ip = (int *)ipp;
if ((int **)ip != ipp) {
fprintf(stderr, "(int *) not compatible with (int **); code won't
work\n");
exit(EXIT_FAILURE);
}
or any portable way without changing the prototype of the fun();

I don't believe there's any completely portable way of doing what you want,
but I'd be happy to be proved wrong.
 
R

Rod Pemberton

Morris Keesan said:
But it's not
guaranteed to be work, because there's no requirement in the language
that (int *) and (int **) are compatible.

6.3.2.3 sub 7 ISO C99 (applies for explicit pointer casting conversions)

"A pointer to an object or incomplete type may be converted to a pointer to
a different
object or incomplete type. If the resulting pointer is not correctly aligned
for the
pointed-to type, the behavior is undefined. Otherwise, when converted back
again, the
result shall compare equal to the original pointer. ... "

Ok, they're convertible and he is converting back... Yes? So, there is no
need for them to have compatible representation, since they are convertible
and the conversion is "round-trip". As long as he doesn't have an alignment
failure, he only has to worry about the legalities of casting an "lvalue".
I don't believe there's any completely portable way of doing what you want,
but I'd be happy to be proved wrong.

What about Ben Bacarisse's code in the reply just above this one?

Although Ben stated that a conversion of a pointer of one type to void *,
and then from that void * to a different type is technically undefined, I
think the stuff below indicates otherwise.

A void * is a pointer to a byte (1). The spec. says a void * has the same
representation as a pointer to char (6.2.5 sub 26 ISO C99). All objects in
C map onto a byte or sequence of bytes (6.2.6.1 sub 2 ISO C99). All
pointers can be converted to a void * and back without loss (6.3.2.3 sub 1
ISO C99). Of course, the C standard redefined a byte from exactly 8-bits,
as "defined" by Bob Bemer and Hugh Ross during the 1960's in the course of
developing ASCII, to an addressable unit of storage ... (3.6 ISO C99) and
elsewhere effectively made a byte 8-bits or more for C.

(1)
http://groups.google.com/group/comp.std.c/msg/74f5906f22a23811?hl=en

I mean, if a void * is a pointer to a byte, and all objects must be
represented as bytes, then how can you convert one type to a void *, but not
technically be able to convert that void * to another type especially if
that other type can also be converted to a void * ? That doesn't make sense
to me. The only way I could understand that being the case is if the
representation of a pointer converted to a void * was different for each
type, but, as I see it, that'd violate 6.2.5 sub 26 of ISO C99... Wouldn't
it?


Rod Pemberton
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top