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

 
 
Willem
Guest
Posts: n/a
 
      07-28-2011
Ike Naar wrote:
) 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.

Which is why god invented macros.

#define NEW(x,n) ((x)=malloc((n) * sizeof(x)))

(If I remember correctly)


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
 
Reply With Quote
 
 
 
 
Angel
Guest
Posts: n/a
 
      07-28-2011
On 2011-07-27, Kenneth Brody <> wrote:
> On 7/27/2011 3:08 AM, Nick Keighley wrote:
> [...]
>> I always thought it should have been an error diagnosed by the
>> compiler- to not have a prototype in scope.

>
> I'm sure many C compilers have that option. For example, Microsoft's C
> compiler has the obvious "/we4013" flag to make such a thing a fatal error
> rather than just a warning.
>
> My guess is that there is too much "legacy code" around w/o prototypes that
> would break if compilers were forced to generate an error.


At the request of a friend, I've lately been trying to get some legacy
code to work with modern toolchains. The results were... interesting, in
the same sense that train wrecks are interesting.

To protect my own sanity, I sadly had to tell my friend I could not help
him.


--
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c
 
Reply With Quote
 
 
 
 
Angel
Guest
Posts: n/a
 
      07-28-2011
On 2011-07-27, Kenneth Brody <> wrote:
>
> Perhaps "all the world's an x86-based Windows box"?


Considering all the issues I encountered with various packages when I
migrated from x86 to x86_64, I'd say that yes, there are a lot of
amateur programmmers who think that way. (I admit having been guilty of
that myself.)

Let's not even go into porting code to systems with a different
endianness, like Sparc or PowerPC...


--
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c
 
Reply With Quote
 
gwowen
Guest
Posts: n/a
 
      07-28-2011
On Jul 27, 6:34*pm, Kenneth Brody <kenbr...@spamcop.net> wrote:

> So, what if you wrote it the "right way" using a cast:
>
> * * *int *pa;
> * * *...
> * * *pa = (int *)malloc(50);


The point was how about the cast prevents me easily *changing* types.
Which it does, but changing types is bug prone. Your "objection" is
completely orthogonal to that point.


int *pa;
pa = (int *)malloc(50); // wrong, if try and fit 50 ints into pa[]
int *pa;
pa = malloc(50); // also wrong.

So lets look at it right.
----------------------------------------------------
int *pa;
..
..
..
pa = (int *)malloc(50*sizeof(int)); // right!
pa = malloc(50*sizeof(int)); // also right!
..
..
..
pa[49] = 0; // OK
----------------------------------------------------


But at some point down the line, we realise we actually need the range
of a 'long' (assuming long > int), so go and change the type of pa.

long int *pa;
..
..
..
pa = (int *)malloc(50*sizeof(int)); // wrong, compile time error
pa = malloc(50*sizeof(int)); // wrong, UB at some unknown point
in the future
..
..
..
pa[49] = 0; // UB for you, can't happen for me.

The cast is saying "I've coded this line under the assumption that the
LHS is of type int*. If this assumption ever changes, can you let me
know? KTHXBYE". Compile-time type checking is good.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-28-2011
Ike Naar <> writes:

> On 2011-07-28, Ben Bacarisse <> 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.


That's a very good point. The duplication here is benign because of the
distance between the two instances. It's diffuse duplication that is
such a problem.

> 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.


As has been pointed out, because the duplication is in one expression
and macro would make sense here. The more complex the expression the
more tempted I'd be to use a macro though for simplex expressions I
think a macro just hides what's going on without much benefit.

> 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.


I'm wary of limiting the use of good ideas because a reader may not know
the language. C is not a big language after all and a comment is all
that's needed to make 100% sure.

--
Ben.
 
Reply With Quote
 
Angel
Guest
Posts: n/a
 
      07-28-2011
On 2011-07-28, gwowen <> wrote:
> pa = (int *)malloc(50*sizeof(int)); // wrong, compile time error
> pa = malloc(50*sizeof(int)); // wrong, UB at some unknown point
> in the future
> .
> .
> .
> pa[49] = 0; // UB for you, can't happen for me.
>
> The cast is saying "I've coded this line under the assumption that the
> LHS is of type int*. If this assumption ever changes, can you let me
> know? KTHXBYE". Compile-time type checking is good.


Of course, had you written

pa = malloc(50 * sizeof *pa);

you would have avoided the issue altogether, as this is always right no
matter what the type of pa might be.


--
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      07-28-2011
On 07/28/2011 07:24 AM, gwowen wrote:
....
> int *pa;
> pa = (int *)malloc(50); // wrong, if try and fit 50 ints into pa[]
> int *pa;
> pa = malloc(50); // also wrong.
>
> So lets look at it right.
> ----------------------------------------------------
> int *pa;
> .
> .
> .
> pa = (int *)malloc(50*sizeof(int)); // right!
> pa = malloc(50*sizeof(int)); // also right!

....
> But at some point down the line, we realise we actually need the range
> of a 'long' (assuming long > int), so go and change the type of pa.
>
> long int *pa;
> .
> .
> .
> pa = (int *)malloc(50*sizeof(int)); // wrong, compile time error
> pa = malloc(50*sizeof(int)); // wrong, UB at some unknown point

....
> The cast is saying "I've coded this line under the assumption that the
> LHS is of type int*. If this assumption ever changes, can you let me
> know? KTHXBYE". Compile-time type checking is good.


Writing your code to remove the unnecessary assumption is better:

pa = malloc(50*sizeof *pa);

Once you've done it right, the cast only gets in the way.
--
James Kuyper
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-28-2011
Angel <angel+> writes:

> On 2011-07-27, Kenneth Brody <> wrote:
>> On 7/27/2011 3:08 AM, Nick Keighley wrote:
>> [...]
>>> I always thought it should have been an error diagnosed by the
>>> compiler- to not have a prototype in scope.

>>
>> I'm sure many C compilers have that option. For example, Microsoft's C
>> compiler has the obvious "/we4013" flag to make such a thing a fatal error
>> rather than just a warning.
>>
>> My guess is that there is too much "legacy code" around w/o prototypes that
>> would break if compilers were forced to generate an error.

>
> At the request of a friend, I've lately been trying to get some legacy
> code to work with modern toolchains. The results were... interesting, in
> the same sense that train wrecks are interesting.


Did you use legacy compiler options or try to get it through with
something more modern like -std=c90? I've have old code (c1985) compile
and work first time. I'd be interested to hear what seemed to be the
main sticking point.

<snip>
--
Ben.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-28-2011
Angel <angel+> writes:

> On 2011-07-28, gwowen <> wrote:
>> pa = (int *)malloc(50*sizeof(int)); // wrong, compile time error
>> pa = malloc(50*sizeof(int)); // wrong, UB at some unknown point
>> in the future
>> .
>> .
>> .
>> pa[49] = 0; // UB for you, can't happen for me.
>>
>> The cast is saying "I've coded this line under the assumption that the
>> LHS is of type int*. If this assumption ever changes, can you let me
>> know? KTHXBYE". Compile-time type checking is good.

>
> Of course, had you written
>
> pa = malloc(50 * sizeof *pa);
>
> you would have avoided the issue altogether, as this is always right no
> matter what the type of pa might be.


Not if the error that gets introduced is in the type of pa. I'm not
advocating for casting the return of malloc, but a meaningful discussion
requires understanding of the opposite view! I think that the cast
malloc people like the feeling that the type is being checked rather
than just allocating storage for whatever type the pointer has.

I am having difficulty imagining a real-world situation where such a
problem won't be detected in other places (which is why I think it's a
weak argument) but there are programs which use the preferred idiom that
can be made silently incorrect by a typo which would provoke a
diagnostic using the cast malloc idiom.

It's interesting that no one from the cast malloc team has presented
such a program, so maybe I am making a case that they have not
considered.

--
Ben.
 
Reply With Quote
 
Angel
Guest
Posts: n/a
 
      07-28-2011
On 2011-07-28, Ben Bacarisse <> wrote:
> Angel <angel+> writes:
>
>> On 2011-07-28, gwowen <> wrote:
>>> pa = (int *)malloc(50*sizeof(int)); // wrong, compile time error
>>> pa = malloc(50*sizeof(int)); // wrong, UB at some unknown point
>>> in the future
>>> .
>>> .
>>> .
>>> pa[49] = 0; // UB for you, can't happen for me.
>>>
>>> The cast is saying "I've coded this line under the assumption that the
>>> LHS is of type int*. If this assumption ever changes, can you let me
>>> know? KTHXBYE". Compile-time type checking is good.

>>
>> Of course, had you written
>>
>> pa = malloc(50 * sizeof *pa);
>>
>> you would have avoided the issue altogether, as this is always right no
>> matter what the type of pa might be.

>
> Not if the error that gets introduced is in the type of pa. I'm not
> advocating for casting the return of malloc, but a meaningful discussion
> requires understanding of the opposite view! I think that the cast
> malloc people like the feeling that the type is being checked rather
> than just allocating storage for whatever type the pointer has.


The type of pa being wrong for whatever purpose is a whole different
issue that is outside of scope of what is being discussed, and does not
invalidate the statement in any way. By that logic, you'd need casts
for every assigment you do, not just memory allocations.

Besides, if you don't know the type and purpose of your own variables,
you have a problem anyway, no matter how many casts you put in.


--
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c
 
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