Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Re: is there anything unstandard in the c part here

Reply
Thread Tools

Re: is there anything unstandard in the c part here

 
 
John Gordon
Guest
Posts: n/a
 
      07-27-2011
In <(E-Mail Removed)> Gareth Owen <(E-Mail Removed)> writes:

> With the cast
> -----------------------------------------------------------------------------
> int *pa;
> /* yadda yadda yadda */
> pa = (char*) malloc(50);
> /* code that presumably assumes 50 elements in pa[] */
> result: compiler error.


I don't see how this would cause a compiler error.

--
John Gordon A is for Amy, who fell down the stairs
http://www.velocityreviews.com/forums/(E-Mail Removed) B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      07-27-2011
John Gordon <(E-Mail Removed)> writes:
> In <(E-Mail Removed)> Gareth Owen <(E-Mail Removed)> writes:
>
>> With the cast
>> -----------------------------------------------------------------------------
>> int *pa;
>> /* yadda yadda yadda */
>> pa = (char*) malloc(50);
>> /* code that presumably assumes 50 elements in pa[] */
>> result: compiler error.

>
> I don't see how this would cause a compiler error.


``(char*) malloc(50)'' is of type char*. pa is of type int*.
char* and int* are not assignment-compatible.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <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"
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      07-27-2011
James Kuyper <(E-Mail Removed)> writes:
[...]
> The whole point of using void* rather than char* (when it's appropriate
> to do so) is the implicit conversions to and from other pointer types.

[...]

It's not the *whole* point. Another point (I'd argue a more
important one) is that any pointer value (other than a function
pointer) can be converted to void* and back again without loss
of information. That would be quite useful even if conversions to
and from void* had to be explicit.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <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"
 
Reply With Quote
 
John Gordon
Guest
Posts: n/a
 
      07-27-2011
In <(E-Mail Removed)> Keith Thompson <(E-Mail Removed)> writes:

> > I don't see how this would cause a compiler error.


> ``(char*) malloc(50)'' is of type char*. pa is of type int*.
> char* and int* are not assignment-compatible.


You learn something new every day! I thought the presence of a cast would
suppress all assignment compatability messages, but not so. The compiler
still checks that the receiving type is compatible with the casted type
and emits a warning (but not an error) if it is not.

--
John Gordon A is for Amy, who fell down the stairs
(E-Mail Removed) B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-27-2011
John Gordon <(E-Mail Removed)> writes:
> In <(E-Mail Removed)> Keith Thompson <(E-Mail Removed)> writes:
>> > I don't see how this would cause a compiler error.

>
>> ``(char*) malloc(50)'' is of type char*. pa is of type int*.
>> char* and int* are not assignment-compatible.

>
> You learn something new every day! I thought the presence of a cast would
> suppress all assignment compatability messages, but not so. The compiler
> still checks that the receiving type is compatible with the casted type
> and emits a warning (but not an error) if it is not.


Casts typically suppress warnings only for the conversion actually
specified by the cast.

For example:

type1 *p1 = NULL;
type2 *p2 = NULL;
type3 *p3 = NULL;

p1 = (type2*)p3;

Assume that type1, type2, and type 3 are not compatible types.

The cast specifies an explicit conversion from type3* to type2*.
No diagnostic is required, and most compilers will assume that you
know what you're doing and not issue a warnings.

But the type of ``(type2*)p3'' is type2*, and we're trying to
assign the result to an object of type type1*. The fact that the
RHS happens to be a cast expression is irrelevant; all that matters
for the "=" operator is its type. Since type2* cannot be implicitly
converted to type1*, a diagnostic is required.

(Note that the standard doesn't distinguish between warnings and
fatal errors. gcc issues non-fatal warnings for some constraint
violations. I personally would prefer these to be errors, but gcc's
behavior satisfies the standard's requirements. Yes, I know you
tell gcc to treat warnings as errors, but that also applies to
optional warnings that don't refer to constraint violations.)

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <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"
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-28-2011
Kenneth Brody <(E-Mail Removed)> writes:

> On 7/27/2011 2:24 AM, Gareth Owen wrote:
>> James Kuyper<(E-Mail Removed)> writes:
>>
>>> What are the drawbacks? I'm not familiar with any.

>>
>> Lets look at the code (roughly) as given
>>
>> char *pa;
>> /* yadda yadda yadda */
>> ..
>> ..
>> ..
>> pa = (char*) malloc(50);
>> ..
>> ..
>> ..
>> /* code that presumably assumes 50 elements in pa[] */
>>
>>
>> Now the advice given was "if you change the type of *pa, the cast is
>> wrong". So lets do that...
>>
>> With the cast
>> -----------------------------------------------------------------------------
>> int *pa;
>> /* yadda yadda yadda */
>> ..
>> ..
>> ..
>> pa = (char*) malloc(50);
>> ..
>> ..
>> ..
>> /* code that presumably assumes 50 elements in pa[] */
>> result: compiler error.

>
> Well, my compiler only gives a warning.
>
>> Take the cast away
>> -----------------------------------------------------------------------------
>> int *pa;
>> /* yadda yadda yadda */
>> ..
>> ..
>> ..
>> pa = malloc(50);
>> ..
>> ..
>> ..
>> /* code that presumably assumes 50 elements in pa[] */
>> result: undefined behaviour unless sizeof(int) == 1
>>
>> The *failure* to cast malloc() has hidden a bug in *exactly* the case for
>> which casting malloc() was held up as being wrong.
>> -----------------------------------------------------------------------------
>>
>> Personally, when I accidentally write buggy code, I want a compiler
>> error rather undefined behaviour. YMMV.

>
> So, what if you wrote it the "right way" using a cast:
>
> int *pa;
> ...
> pa = (int *)malloc(50);
>
> Still has UB if you assume that pa contains 50 ints. Your "buggy
> code" still invokes UB. What happened to your "advantage" with the
> cast?


The argument (such as it is) is not that changing the cast fixes
anything but that having it there in the first place (in this case as a
(char *) cast) alerts the programmer to a line the needs fixing. This
will be either because the type of the pointer has changed or because
there is a typo and the assignment is being made to the wrong pointer
(or the typo is in the declaration of the pointer).

The first of these is covered by the p = malloc(n * sizeof *p) idiom and
the second is probably quite rare. What's more, it is protection by
duplication, and duplication is anathema to programmers -- hence the
preferred typeless idiom.

--
Ben.
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      07-28-2011
On 07/27/2011 01:42 PM, John Gordon wrote:
> In <(E-Mail Removed)> Keith Thompson <(E-Mail Removed)> writes:
>
>>> I don't see how this would cause a compiler error.

>
>> ``(char*) malloc(50)'' is of type char*. pa is of type int*.
>> char* and int* are not assignment-compatible.

>
> You learn something new every day! I thought the presence of a cast would
> suppress all assignment compatability messages, but not so.


The presence of a cast to a type compatible with the destination type
has precisely that effect. Such casts are quite common, which is
probably what led you to that conclusion.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      07-28-2011
On 07/27/2011 11:24 AM, Keith Thompson wrote:
> James Kuyper <(E-Mail Removed)> writes:
> [...]
>> The whole point of using void* rather than char* (when it's appropriate
>> to do so) is the implicit conversions to and from other pointer types.

> [...]
>
> It's not the *whole* point. Another point (I'd argue a more
> important one) is that any pointer value (other than a function
> pointer) can be converted to void* and back again without loss
> of information. That would be quite useful even if conversions to
> and from void* had to be explicit.


The property you describe is also mandated for char*, as a side-effect
of char* being required to have the same representation as void*.
Therefore, that property is not a reason for using void* rather than
char*. If void* had never been invented, the standard could have
assigned that property to char* directly. I'm sure that char* already
had that property on most, if not all, pre-standard C compilers.

--
James Kuyper
 
Reply With Quote
 
Uno
Guest
Posts: n/a
 
      07-28-2011
On 07/26/2011 04:11 PM, (E-Mail Removed) wrote:
> Bill Waddington<(E-Mail Removed)> wrote:
>>
>> Oh my. Someone who knows what "begging the question" actaully means.

>
> There are still lots of us around, although we are greatly outnumbered.


I think it was when the phrase left logic, a small part of mathematics,
where it denoted that which bring proves a proposition by assuming it,
and became something that would constantly flow out of the mouths of
talking heads on tv, where it's taken to mean that which motivates
another question which then oozes out of their mouths, so the usage is
entirely different.

Current usage: "...which begs the question, does casey anthony support
Obama?"

Old usage: "That begs the question." [Period.] (Long awkward silence
as all parties absorb that somebody's method is called out.)
--
Uno
 
Reply With Quote
 
Ike Naar
Guest
Posts: n/a
 
      07-28-2011
On 2011-07-28, Ben Bacarisse <(E-Mail Removed)> wrote:
> The first of these is covered by the p = malloc(n * sizeof *p) idiom and
> the second is probably quite rare. What's more, it is protection by
> duplication, and duplication is anathema to programmers -- hence the
> preferred typeless idiom.


To be fair, the preferred idiom also relies on duplication: in

p = malloc(n * sizeof *p);

the duplication is benign, but if the pointer expression
becomes more complicated, as in

*(*co_matrix)[pivot] = malloc(n * sizeof **(*co_matrix)[pivot]);

the duplication becomes a bit of a nuisance.
Because of the duplicated complexity, a silly mistake like

*(*co_matrix)[pivot] = malloc(n * sizeof *(*co_matrix)[pivot]);

may creep in, which is not caught by the compiler, and is easily
overlooked during code inspection.

Also, if the pointer expression has side effects:

a[j++] = malloc(n * sizeof *a[j++]);

although the preferred idiom works okay here (thanks to the fact that
sizeof does not evaluate its operand), this may confuse the reader.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: is there anything unstandard in the c part here Nick Keighley C Programming 16 08-01-2011 03:20 PM
Re: is there anything unstandard in the c part here Barry Schwarz C Programming 11 07-27-2011 06:10 PM
Does anyone Here know anything about when Digtial phones will bereleased David S. Computer Support 13 08-12-2005 03:28 AM
ActiveX apologetic Larry Seltzer... "Sun paid for malicious ActiveX code, and Firefox is bad, bad bad baad. please use ActiveX, it's secure and nice!" (ok, the last part is irony on my part) fernando.cassia@gmail.com Java 0 04-16-2005 10:05 PM



Advertisments