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**??
"((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?
> > 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**.
>
implicit cast here too. leaving compiler to cast 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**??
>
> What did your compiler tell you?
compiling with gcc, it issues a two waring and can run the code fine.
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 ===|
> #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 *)
> *p=10;
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));
}
First, a cast is an explicit conversion. That's not what you are talking
about here. You want fun() to allocate sizeof (int) bytes and put their
address in p in main(). Like this:
void fun(int **i) {
*i = malloc(sizeof **i);
}
int main(void) {
int *p;
fun(&p);
*p = 10;
printf("%d\n", *p);
return 0;
}
No cast involved or needed. Of course you might test the return from
malloc().
--
Joe Wright
"If you think Health Care is expensive now, wait until it's free."
> #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?
--
Ben.
I know this is portable but this was to illustrate the problem..
i dont want this..
>On Jul 3, 8:18�am, Mark Bluemel <mark.blue...@googlemail.com> wrote:
>> On 3 July, 15:53, Praveen Raj <praveenraj1...@gmail.com> wrote:
>>
>> > #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...
>>
>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.
--
Remove del for email
>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.
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.
> 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..
>
> > 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 *)> *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*???
> On Jul 3, 8:54 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
<snip alternate code>
>> which is well-defined and portable. Is that what you wanted to do?
>>
>> --
>> Ben.
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?
--
Ben.
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..
> On Jul 3, 8:28 am, "Morris Keesan" <kee...@alum.bu.edu> wrote:
>> On Fri, 03 Jul 2009 10:53:23 -0400, Praveen Raj <praveenraj1...@gmail.com>
>> wrote:
>>
>> > #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),
>
> 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 *.
<snip>
>> > 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 *)> *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.
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>
--
Ben.
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();
> #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.]
--
Ben.
<snip>
> 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.
Fine, but you'll leak the memory when fun() exits, unless you
release it yourself within fun().
> so i need to cast it and do all the things other way around..
Casting isn't your problem. Impossibility is your problem. The
function does not receive the p object, merely its value. Casting
that value to int ** does not magically retrieve the original
object. So the solution is to fix the prototype. That violates the
constraints of your problem, but in this case that's simply an
indication that the constraints are misguided.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Forged article? See
http://www.cpax.org.uk/prg/usenet/comp.lang.c/msgauth.php
"Usenet is a strange place" - dmr 29 July 1999
It looks like it might work but "If you lie to the compiler, it will get
its revenge."
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?
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
> #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.
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
You've mentioned the possibility of misalignment, cited the part of the
standard that says that the behavior of the program is undefined if that
possibility comes up; yet you write as though that possibility isn't
very important. Why?
Probably because the pointer is allocated with malloc().
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
That fact wasn't mentioned in the message I was responding to. I could
have traced backward through the thread, but it didn't seem to be
necessary. It would have been clearer if Ron had mentioned that as the
reason he wasn't worrying about misalignment.
If, as Praveen says, the prototype for fun() is externally imposed, then
I strongly suspect that the package it is imposed by will try to
dereference it, as a pointer to int. Therefore, this strikes me as a
very risky way of doing things.
> James Kuyper wrote:
> ) You've mentioned the possibility of misalignment, cited the part of the
> ) standard that says that the behavior of the program is undefined if
> that
> ) possibility comes up; yet you write as though that possibility isn't
> ) very important. Why?
>
> Probably because the pointer is allocated with malloc().
No, it's not. The pointer we're concerned with is the pointer which is
passed as an argument to fun(), then dereferenced to have malloc()'s
return value stored where it's pointing.
But I didn't say anything here about the representation. I was just using
the term "compatible" (which I don't believe has any definition in the
language standard) to suggest that (int *) and (int **) might not be
convertible one-to-the-other in a defined way, which you acknowledge here -
"As long as he doesn't have an alignment failure"
...
> 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 * ?
"As long as [you don't] have an alignment failure."
Consider a machine on which integers MUST be aligned on an even byte
boundary.
Consider, on that machine, a (char *) pointing to bye 148793.
Convert that (char *) to a (void *) -- no problem. Convert that (void *)
to
an (int *). On some implementations, even the attempt to store that value
in
an (int *) will cause program failure. On others, the failure won't occur
until
you try to dereference the misaligned pointer. On still others, the
conversion
could change the value of the pointer, making it point to a different
address.
It's undefined, hence non-portable.
See section 6.2.7: "Compatible type and composite type". Representation
is quite relevant.
> ... to suggest that (int *) and (int **) might not be
> convertible one-to-the-other in a defined way, which you acknowledge here -
> "As long as he doesn't have an alignment failure"
The conversion is defined, but only to the extent that it is reversible,
unless there's an alignment problem. I was wrong to accept Willem's
assertion that the relevant pointer had been the result of the a call to
malloc(), in which case alignment would not be an issue. The relevant
pointer is &p, which is not necessarily correctly aligned for conversion
into an int*.
Your belief is incorrect -- "compatible type" is a well-defined, and
very important, technical term defined in 6.2.7.
--
Larry Jones
Somebody's always running my life. I never get to do what I want to do.
-- Calvin
He is converting from int ** to int * and then back to int **. Yes?
The original int** pointer is required to be aligned to a byte for all
objects. It's also correctly aligned for the object's type. The cast to
int * is required to be aligned to the same byte. Although byte aligned, it
may or may not be properly aligned for the resulting object type. Use of
int * is undefined, but only for platforms with alignment issues. It's
defined for platforms without alignment issues. But, in his revision above,
he doesn't use the intermediate pointer int *. He converts the int *
pointer back to an int** pointer. It's required that this conversion be
equivalent. It must be aligned to a byte, be correctly aligned to the
original type, and be equal to the original pointer. There can't be any
pointer lossage or conversion error due to misalignment. Effectively, this
is a "do nothing" or "round trip" or lossless pointer conversion.
Rod Pemberton
This doesn't affect the pointer conversion. It affects pointer usage.
All (non-bitfield) objects are required to be byte aligned (6.2.6.1 sub 2
ISO C99). Therefore, all pointers must be byte aligned to be compliant,
even if the spec. doesn't require all pointers to have the same
representation (6.2.5 sub 26 ISO C99). Ugh... Historically, most systems
have standardized on an 8-bit data type due to Bob Bemer's ASCII and EBCDIC
work. But, even if a system is "word" (16-bit) aligned, as long as a C byte
is defined as a "word", C will work on the system. Alignment issues occur
when you introduce a type to the C system that isn't or can't always be
aligned to a C byte, or isn't accessable due to alignment from every C byte.
> Consider a machine on which integers MUST be aligned on an even byte
> boundary.
... "word" aligned or addressable ... PDP-11, Cray ... FYI, you could've
picked a PDP-10 (36-bit word, 7-bit char, 18-bit addresses) or IBM 705 or
other early 36-bit scientific computers... ;-) If C requires 8-bit
characters, what do you do with a 7-bit char PDP-10? It pre-dates C
development (PDP-11, 16-bit word, 8-bit byte addressable ... for ASCII)...
> Consider, on that machine, a (char *) pointing to bye 148793.
> Convert that (char *) to a (void *) -- no problem.
No problem.
> Convert that (void *) to an (int *).
No problem.
> On some implementations, even the attempt to store that value
> in an (int *) will cause program failure.
First, they could've defined a C byte as having a alignment of two host
bytes thereby likely eliminating the issue.
Second, you used it while knowing it has an alignment issue for that
platform...!
> It's undefined, hence non-portable.
As the spec. says, usage is undefined on that platform. ... "for the
pointed-to-type" ... usage, i.e., "behavior", is undefined.
Does failure on one (ancient or obscure) system imply the code is
non-portable? I'd say no.
There were quite a few systems that implemented C, but aren't fully spec.
compliant because they predated the spec. It's still portable C. It'll
work on modern systems and most microprocessors and cpu's back to the mid
'70's. The C spec. doesn't define many things which have been standardized
and are required for "portability", like the time epoch (AT&T Sys V, and
later POSIX), or character sets (esp. ASCII, also EBCDIC), or an 8-bit byte
addressable unaligned architecture, which are needed to implement C fully
and completely.
When was the last time anyone saw a system that didn't use
binary, one's and two's complement? They were working on trinary systems
some years ago, using tri-level voltages... If someone implement's C on
such a system, is all the C code of the past four decades non-portable,
since the spec. doesn't specify trinary arithmetic? (No.)
Just because a non-compatible system or a non-compliant system doesn't mean
the code is non-portable. It just means it's non-functioning on that
system. It's upto the programmer's for that host to fix the issues, or
recode their compiler. We're looking at the issue four decades after the
problems were solved with
a C specification that failed to record the solutions in the name of
portability. They know what the world standardized on: 8-bit (unaligned)
byte addressable memory with ASCII.
Rod Pemberton
No, it affects the conversion.
C99 6.3.2.3p7:
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.
Note that this isn't about the alignment of a pointer object
(conversions yield values, not objects), it's about the alignment of
the address to which the pointer value points.
[...]
Well, yes; all objects in C except bit-fields are required to be byte
aligned. Since it's a constraint violation to attempt to take the
address of a bit-field, pointers to object types must point to byte
aligned locations. That fact doesn't really have anything to do with
this issue.
The alignment requirement that is referred to by 6.3.2.3p7 is not the
implicit requirement in 6.2.6.1p2 that non-bitfield objects be aligned
on byte boundaries, which is defined by the standard. It is referring to
alignment in the more general sense defined in 3.2p1: "requirement that
objects of a particular type be located on storage boundaries with
addresses that are particular multiples of a byte address". The only
types for which you can derive the fact that the alignment requirement
must 1 byte are the character types. The alignment requirements for any
other types (such as 'int' and 'int*') are unspecified by the standard,
and can be greater than 1 byte.
An implementation must arrange for 'p' to be correctly aligned to hold
an object of type int*. However, there's no requirement that the
location of p be correctly aligned for an object of type 'int'.
Therefore, conversion of &p to (int*) may have undefined behavior. It
doesn't matter that the resulting pointer is never dereferenced;
6.3.2.3p7 says that the conversion itself that has undefined behavior.
<snip>
> Does failure on one (ancient or obscure) system imply the code is
> non-portable? I'd say no.
>
> There were quite a few systems that implemented C, but aren't fully spec.
> compliant because they predated the spec. It's still portable C.
what?
> It'll
> work on modern systems and most microprocessors and cpu's back to the mid
> '70's. The C spec. doesn't define many things which have been standardized
> and are required for "portability", like the time epoch (AT&T Sys V, and
> later POSIX), or character sets (esp. ASCII, also EBCDIC), or an 8-bit byte
> addressable unaligned architecture, which are needed to implement C fully
> and completely.
>
> When was the last time anyone saw a system that didn't use
> binary, one's and two's complement? They were working on trinary systems
> some years ago, using tri-level voltages... If someone implement's C on
> such a system, is all the C code of the past four decades non-portable,
> since the spec. doesn't specify trinary arithmetic? (No.)
>
> Just because a non-compatible system or a non-compliant system doesn't mean
> the code is non-portable. It just means it's non-functioning on that
> system.
I don't see the difference between "non-functional [on a particular
system]" and "non-portable"
> It's upto the programmer[]s for that host to fix the issues, or
> recode their compiler. We're looking at the issue four decades after the
> problems were solved with
> a C specification that failed to record the solutions in the name of
> portability. They know what the world standardized on: 8-bit (unaligned)
> byte addressable memory with ASCII.
there are no current system that require alignment on non-byte
boundaries?
I thought the trend with RISC stuff was to become *more* fussy about
alignment. Don't even pentiums have alignment issues?
> On 5 July, 23:08, "Rod Pemberton" <do_not_h...@nohavenot.cmm>
> wrote:
<snip>
> They know what the world standardized on: 8-bit
>> (unaligned) byte addressable memory with ASCII.
>
> there are no current system that require alignment on non-byte
> boundaries?
There are no current systems that use character sets other than
ASCII?
Nick, you might want to check out RP's posting history before
wasting too much more time.
ah, he's an all-the-worlds-a-vax person is he?
[for "VAX" read whatever is this weeks favorite model]
|I know this is portable but this was to illustrate the problem..
|i dont want this..
Based on your responses to the well-meant attempts of others to help you, I
have to ask:
Are you trying to get some programming done, or are you training to become a
language lawyer?
In either case, you need to make your intentions clear.
HTH -- mecej4
Okay, we're on the same page here.
> Since it's a constraint violation to attempt to take the
> address of a bit-field,
Other than just saying "it's a constraint violation", do you understand why
you _can't_ do this? If a byte is the minimum addressable unit of storage,
and all non-bitfield objects are aligned on byte boundaries, how do you
construct a pointer to point in-between bytes? to some un-addressable bit?
> pointers to object types must point to byte
> aligned locations.
Yes.
> That fact doesn't really have anything to do with
> this issue.
That's exactly what we've been discussing. 6.3.2.3p7 says the pointer
conversion from a type resulting in the same type is loss-less and it's
usage, if misaligned, is undefined.
> The alignment requirement that is referred to by 6.3.2.3p7 is not the
> implicit requirement in 6.2.6.1p2 that non-bitfield objects be aligned
> on byte boundaries, which is defined by the standard.
It's not? How does a pointer point to an object then... If it's not, then
no pointer can point to any object. Is that what you're claiming? Really?
> It [6.3.2.3p7] is referring to
> alignment in the more general sense defined in 3.2p1: "requirement that
> objects of a particular type be located on storage boundaries with
> addresses that are particular multiples of a byte address".
Except for the fact that one specifies bit-fields as excluded for obvious
reasons and the other fails to do so, there is no difference between
6.3.2.3p7 and 3.2p1.
> The only
> types for which you can derive the fact that the alignment requirement
> must 1 byte are the character types.
True. But, all types, except bitfields, must be byte aligned. They are
aligned to a byte boundary. If an int has a size of 4 and is aligned, it's
byte aligned to a byte boundary, every fourth byte...
> The alignment requirements for any
> other types (such as 'int' and 'int*') are unspecified by the standard,
> and can be greater than 1 byte.
... but are still aligned on a byte boundary. A byte is the minimum
addresable unit. You can't point a pointer in-between a byte.
> An implementation must arrange for 'p' to be correctly aligned to hold
> an object of type int*.
True.
> However, there's no requirement that the
> location of p be correctly aligned for an object of type 'int'.
True. But, this has nothing to do with the issue.
> Therefore, conversion of &p to (int*) may have undefined behavior.
That's not what 6.3.2.3p7 says. It says the pointer behavior for the
pointed-to type is undefined. It says nothing about the pointer conversion
being undefined.
> It
> doesn't matter that the resulting pointer is never dereferenced;
> 6.3.2.3p7 says that the conversion itself that has undefined behavior.
No.
RP
I'm not sure to what you're referring to. You constantly post incorrect
statements. I've corrected you numerous times. I've shown your posted code
to be wrong numerous times. I don't read and post here regularly, but I can
only recall one time that you posted correct code. And, I stated so. Keith
Thompson, who I don't care for either and who gets many things wrong too,
has had long periods where he has corrected you almost incessantly too. So,
the fact that you keep insulting me, by telling others _I'm_ the problem is
really annoying and is extremely childish.
> There are no current systems that use character sets other than
> ASCII?
I didn't say that. I said the world standardized on ASCII. HUGE
difference, but you never notice things like this, do you? And, the world
has, until recently been stuck with ASCII and EBCDIC. So, feel free to name
one non-IBM system that is current, i.e., within the last year and a half,
which can represent Germanic languages, and that doesn't use ASCII. If you
want to mention a system that uses an Oriental language, because you can't
find a Germanic one, go ahead. And then, feel free to post the quantities
of systems used from 1974 to 2007 broken down by ASCII and EBCDIC. The
numbers will confirm the world standardized on ASCII.
RP
What what? C was standardized after many existing implementations. It's
been around since 1974 but was standardized in 1989. So, what what? What
do you mean by "what?" ?
> > Just because a non-compatible system or a non-compliant system doesn't
mean
> > the code is non-portable. It just means it's non-functioning on that
> > system.
>
> I don't see the difference between "non-functional [on a particular
> system]" and "non-portable"
Look up portable and then look up functional. What you're saying is that
code that compiles on 99.999% of all machines, but doesn't compile on
00.001% is non-portable. If it compiles on 99.999% of all machines, it's
portable. It's non-functional on 00.001%. So, where is the boundary
between being portable and functional. If say 90%, 80%, 75%, maybe even
60%, then it's still portable. Today, I think we're much closer to 100%
than we were in 1974. I'd say 98%.
> > It's upto the programmer[]s for that host to fix the issues, or
> > recode their compiler. We're looking at the issue four decades after the
> > problems were solved with
> > a C specification that failed to record the solutions in the name of
> > portability. They know what the world standardized on: 8-bit (unaligned)
> > byte addressable memory with ASCII.
>
> there are no current system that require alignment on non-byte
> boundaries?
Not that I'm aware of, but I wouldn't doubt it some still obscure and custom
systems, say Crays, aren't.
What would they align on? A nybble? three-bits? nine-bits? A byte is the
minimum addressable unit in C, you can't point to something in-between. A
pointer must point to a byte boundary. Alignment is still on a byte
boundary even if an object is two byte or four byte aligned.
> I thought the trend with RISC stuff was to become *more* fussy about
> alignment. Don't even pentiums have alignment issues?
Wouldn't doubt it.
RP
I've been over this, look back six messages... Or, look down some...
> C99 6.3.2.3p7:
>
> 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.
>
Why do you always come in late, in the wrong part of the thread, then
requote, say "that's wrong", when this was already discussed elsewhere in
this same thread?
> Note that this isn't about the alignment of a pointer object
> (conversions yield values, not objects), it's about the alignment of
> the address to which the pointer value points.
As I said, all pointers in C must point to a byte boundary, because all
objects, except bitfields, in C have byte alignment. Depending on the
object, the pointer may point to every byte boundary, every other byte
boundary, every fourth byte boundary, etc, but it still points to a byte
boundary. A byte is the minimum addressable unit in C, you can't point to
something in-between.
RP
You claimed that an alignment failure doesn't affect the pointer
conversion. You were wrong. I replied immediately to the message in
which you made that incorrect claim.
[snip]
No. I understand why an implemention could in fact do this. However,
in most cases it's horribly inefficient, and the standard was
therefore explicitly written to not mandate such inefficiency.
> ... If a byte is the minimum addressable unit of storage,
The C byte is the minimum unit of storage that can be addressed by C
code. It need not be the same as the hardware addressable unit, and
there are many implementations where it is much smaller.
> and all non-bitfield objects are aligned on byte boundaries, how do you
> construct a pointer to point in-between bytes? to some un-addressable bit?
By creating a pointer that consists of a byte address and a bit
offset. Much the same approach must already be used to emulate char*
pointers on machines where the addressable storage unit was deemed, by
the implementor, to be too large for use as a C byte. The issue isn't
whether it's feasible for an implementation to provide bit-pointers;
it certainly is feasible. The issue is whether the C standard mandates
them; and it very specifically excludes the possibility.
> > That fact doesn't really have anything to do with
> > this issue.
>
> That's exactly what we've been discussing. 6.3.2.3p7 says the pointer
> conversion from a type resulting in the same type is loss-less and it's
> usage, if misaligned, is undefined.
If byte-alignment were the only thing it was talking to, how could the
pointer ever get misaligned? Misaligned C pointers is a meaningful
concept only in the context of alignment requirements larger than 1
byte.
> > The alignment requirement that is referred to by 6.3.2.3p7 is not the
> > implicit requirement in 6.2.6.1p2 that non-bitfield objects be aligned
> > on byte boundaries, which is defined by the standard.
>
> It's not? How does a pointer point to an object then...
By identifying the location that the object starts at. This location
might be a word boundary, with (for example) 4 bytes to a word.
Pointers of that type might be incapable of pointing at positions
withing a word. This is all allowed by the C standard. char* and void*
can't have this characteristic, but long* and double* might, and
there's real machines on which they do.
> ... If it's not, then
> no pointer can point to any object.
No such conclusion can be validly drawn from my assertion.
> ... Is that what you're claiming?
Not at all.
> ... Really?
Really - not at all.
> > It [6.3.2.3p7] is referring to
> > alignment in the more general sense defined in 3.2p1: "requirement that
> > objects of a particular type be located on storage boundaries with
> > addresses that are particular multiples of a byte address".
>
> Except for the fact that one specifies bit-fields as excluded for obvious
> reasons and the other fails to do so, there is no difference between
> 6.3.2.3p7 and 3.2p1.
Yes there is. 3.2p1 defines what alignment means. 6.3.2.3p7 says,
among other things, that the behavior is undefined if you attempt to
convert a misaligned pointer. I see that as a rather huge difference,
my self.
> > The only
> > types for which you can derive the fact that the alignment requirement
> > must 1 byte are the character types.
>
> True. But, all types, except bitfields, must be byte aligned.
Certainly, and irrelevant to 6.3.2.3p7.
> They are
> aligned to a byte boundary. If an int has a size of 4 and is aligned, it's
> byte aligned to a byte boundary, every fourth byte...
Elsewhere, you seem to be implying that the only relevant alignment
requirement is 1 byte. However, in the above sentence it seems as
though you might be thinking that the alignment requirement has to
match the size. Is that what you're saying? if so, that's not the
case. A 4-byte int could have an alignment requirement of 2. What can
be proven by combining C's rules for pointer arithmetic, arrays, and
sizeof, is that the size of a data type must be an integer multiple of
the alignment requirement. The ratio of the size to the alignment
requirement could be 1, but is not required to be.
> > The alignment requirements for any
> > other types (such as 'int' and 'int*') are unspecified by the standard,
> > and can be greater than 1 byte.
>
> ... but are still aligned on a byte boundary. A byte is the minimum
> addresable unit. You can't point a pointer in-between a byte.
True, but the question is not whether you can point a pointer between
bytes. Let's consider an implementation where int is 4 bytes and has
an alignment requirement of 2. What 6.3.2.3p7 is saying is that the
following code:
int array[4];
int *pi = (int*)(1+(char*)array);
has undefined behavior, because the pointer value 1+(char*)array
points at an address which is incorrectly aligned to hold an int.
> > An implementation must arrange for 'p' to be correctly aligned to hold
> > an object of type int*.
>
> True.
>
> > However, there's no requirement that the
> > location of p be correctly aligned for an object of type 'int'.
>
> True. But, this has nothing to do with the issue.
>
> > Therefore, conversion of &p to (int*) may have undefined behavior.
>
> That's not what 6.3.2.3p7 says. It says the pointer behavior for the
> pointed-to type is undefined. It says nothing about the pointer conversion
> being undefined.
"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
aligned57) for the
pointed-to type, the behavior is undefined."
In the above sentence "the behavior is undefined" can only refer to
the behavior when such a pointer is "converted to a pointer to a
different type or incomplete type". Not the behavior after the
conversion, but the behavior of the conversion itself.
This is not just a pedantic debate about what the standard means; in
the real world there are systems where pointers to different types are
handled in different fashions. For instance, there may be
implementations with CHAR_BIT==8 on systems where the hardward
addressable unit (word) is 32 bits. On such systems, pointers to some
types that have a size which is a multiple of the word size may
identify only which word the object starts in, and be physically
incapable of representing positions that are not at the beginning of
word. 6.3.2.3p7 was written for the explicit purpose of allowing such
implementations to qualify as conforming to the standard.
> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
> news:htydnRwvGa0VOszX...@bt.com...
>> Nick, you might want to check out RP's posting history before
>> wasting too much more time.
>
> I'm not sure to what you're referring to.
That's wonderful; I love it. (Hint: count the prepositions.)
> You constantly post incorrect statements.
Given the imperfection of humanity and the thousands of articles
I've posted to this group, that's inevitable. So?
> I've corrected you numerous times.
Message-IDs, please.
> I've shown your posted code to be wrong numerous times.
Message-IDs, please.
> I don't read and post here regularly, but I can
> only recall one time that you posted correct code.
Then you hardly read here at all.
> And, I stated so.
<shrug>
> Keith Thompson, who I don't care for either and who gets many
> things wrong too,
Everyone gets many things wrong. It's human nature.
> has had long periods where he has corrected you almost incessantly
> too.
Yeah, that's what we do. And I've corrected him, too (although he
probably makes fewer mistakes than I do because he's more patient
than I am). Er, so what?
> So, the fact that you keep insulting me, by telling others
> _I'm_ the problem is really annoying and is extremely childish.
I didn't insult you. I didn't tell others you're the problem. I
simply suggested to Nick that he might want to check out your
posting history. What is it about your posting history that you
find insulting and problematical?
>> There are no current systems that use character sets other than
>> ASCII?
>
> I didn't say that. I said the world standardized on ASCII.
But it didn't. Firstly, the IBM world was never at home with ASCII
and mostly used/uses EBCDIC. DisplayWrite (an IBM word processor)
even stored its documents in EBCDIC, despite being a PC-based
program. Secondly, practically no computer uses ASCII per se.
Mostly they use some kind of extension thereof.
> HUGE difference, but you never notice things like this, do you?
Small difference, and now that you've pointed it out it's easy to
see how irrelevant it is.
> And, the world has, until recently been stuck with ASCII and
> EBCDIC.
Well, only if you ignore all the non-ASCII non-EBCDIC systems.
> So, feel
> free to name one non-IBM system that is current, i.e., within the
> last year and a half,
> which can represent Germanic languages, and that doesn't use
> ASCII.
Any of them, really. ASCII is a 7-bit code, and you'll be
hard-pressed to find a system that uses 7-bit bytes. You'll be even
harder-pressed to find a system that has 8-bit bytes and that is
prepared to waste one bit per byte so that it can adopt an
antiquated 7-bit code.
> If you want to mention a system that uses an Oriental
> language, because you can't
> find a Germanic one, go ahead.
Oh, finding them isn't the problem.
> And then, feel free to post the quantities
> of systems used from 1974 to 2007 broken down by ASCII and EBCDIC.
ASCII: 0
EBCDIC: see IBM sales reports
Other: everything else
> The numbers will confirm the world standardized on ASCII.
Yeah, right.
Kiki, don't lose that number...!
In some sense, then, it could be said that virtually every computer uses
ASCII. :) Did ASCII require systems be 7-bit?
-Beej, memories of PETSCII--no { } characters!
> Richard Heathfield <r...@see.sig.invalid> wrote:
>>Secondly, practically no computer uses ASCII per se. Mostly they
>>use some kind of extension thereof.
>
> In some sense, then, it could be said that virtually every
> computer uses
> ASCII. :) Did ASCII require systems be 7-bit?
ASCII, as far as I'm aware, is just a 7-bit character set, not a
collection of requirements. But a system that uses an 8-bit
character set is not using ASCII, because ASCII is not an 8-bit
character set.
> -Beej, memories of PETSCII--no { } characters!
In ATASCII, four of the characters, which looked like random
scribbles, could be arranged in a 2x2 square to form a portrait of
a man smoking a pipe. Another two of the symbols could be placed
side by side to give the Atari logo.
<http://en.wikipedia.org/wiki/J.R._"Bob"_Dobbs>