473,854 Members | 1,449 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

why is casting malloc a bad thing?

Hello,

I saw on a couple of recent posts people saying that casting the return
value of malloc is bad, like:

d=(double *) malloc(50*sizeo f(double));

why is this bad? I had always thought (perhaps mistakenly) that the
purpose of a void pointer was to cast into a legitimate date type. Is
this wrong? Why, and what is considered to be correct form?

thanks,

Brian Blais

Nov 14 '05
231 23330
Dan Pop wrote:
In <bv**********@n ews.tudelft.nl> Sidney Cadot <si****@jigsaw. nl> writes:

I know that in most contexts this isn't necessary because it will be
assigned to a typed pointer immediately after, but still it brings the
expression under the compiler's type checking regime a little bit
earlier, preventing such silliness as:

int *x = malloc(50*sizeo f(double));

since

int *x = (double *)malloc(50*siz eof(double));

is an error.

Now I've seen all the counter-arguments to this by now, but in the end I
simply feel that malloc(50*sizeo f(double)) is incorrectly typed as
void*, and that's all there is to it as far as I am concerned.

In most cases, malloc(50*sizeo f(double)) is considered bad style.
Consider the alternative:

double *x = malloc(50 * sizeof *x);


That's funny, my lone expression seems to have turned into a full-blown
declarator/initializer as if by magic.

My point, as you know by now but choose to ignore, is that the malloc
expression itself should be properly typed as a double*.
Casting to double * not only doesn't add anything, because there is no
place left for the error you're talking about, but it is a maintenance
headache if the type of x ever needs to be changed, say to pointer
to long double: instead of making one change, you have to make two,
That's true. In fact, it's more of a "maintenanc e headache" than what
your preferred notation introduces when changing the identifier name
(but only slightly).
for no redeeming advantage.


The redeeming advantage, to me, is the knowledge that I have corrected
the misconception of the compiler about the type of an object at the
earliest possible opportunity.

That way, I don't have to rely on the semantics of C with regard to
allowing void*-to-any* assignments, which I think are an ugly wart on
C's type safety system.

An analogy may help. Here in Holland, it aggrieves me to say, we have no
law forbidding the wearing of white socks under a suit. But that doesn't
mean I don't make an effort to avoid being dressed like that.

Best regards,

Sidney

Nov 14 '05 #171
I have not seen the base article, hence my response to this:
Da*****@cern.ch (Dan Pop) wrote in message news:<bv******* ****@sunnews.ce rn.ch>...
IIRC, the pre-ANSI C mallloc returned char *. That required an
explicit cast any time its return value was not assigned to a char *.
So, it is very likely that Kernighan was doing it out of habit.


It did indeed return a char *. And no, it did not require an explicit
cast any time its return value was not assigned to a char *. Pre-ANSI
C did not require casts on pointer assignments, the requirement came
with ANSI C.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #172
In <bv**********@n ews.tudelft.nl> Sidney Cadot <si****@jigsaw. nl> writes:
Dan Pop wrote:
In <bv**********@n ews.tudelft.nl> Sidney Cadot <si****@jigsaw. nl> writes:

I know that in most contexts this isn't necessary because it will be
assigned to a typed pointer immediately after, but still it brings the
expression under the compiler's type checking regime a little bit
earlier, preventing such silliness as:

int *x = malloc(50*sizeo f(double)); ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^
since

int *x = (double *)malloc(50*siz eof(double)); ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
is an error.

Now I've seen all the counter-arguments to this by now, but in the end I
simply feel that malloc(50*sizeo f(double)) is incorrectly typed as
void*, and that's all there is to it as far as I am concerned.

In most cases, malloc(50*sizeo f(double)) is considered bad style.
Consider the alternative:

double *x = malloc(50 * sizeof *x);


That's funny, my lone expression seems to have turned into a full-blown
declarator/initializer as if by magic.


No magic at all: you have used it as such, in your own examples. Hence
my counterexample.
My point, as you know by now but choose to ignore, is that the malloc
expression itself should be properly typed as a double*.
Nope, because it never used as an expression by itself: it's always used
either as an initialiser or as a subexpression of a wider expression
which establishes its intended type.
Casting to double * not only doesn't add anything, because there is no
place left for the error you're talking about, but it is a maintenance
headache if the type of x ever needs to be changed, say to pointer
to long double: instead of making one change, you have to make two,


That's true. In fact, it's more of a "maintenanc e headache" than what
your preferred notation introduces when changing the identifier name
(but only slightly).


If you ever have to change identifier names in your code, there is
something very wrong with your coding methodology.
for no redeeming advantage.


The redeeming advantage, to me, is the knowledge that I have corrected
the misconception of the compiler about the type of an object at the
earliest possible opportunity.


The compiler has no misconceptions about anything.
That way, I don't have to rely on the semantics of C with regard to
allowing void*-to-any* assignments, which I think are an ugly wart on
C's type safety system.
I'm afraid that few C programmers share your views.
An analogy may help. Here in Holland, it aggrieves me to say, we have no
law forbidding the wearing of white socks under a suit. But that doesn't
mean I don't make an effort to avoid being dressed like that.


So, what kind of socks are you wearing under a white suit?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #173
In <Hs********@cwi .nl> "Dik T. Winter" <Di********@cwi .nl> writes:
I have not seen the base article, hence my response to this:
Da*****@cern.ch (Dan Pop) wrote in message news:<bv******* ****@sunnews.ce rn.ch>...
IIRC, the pre-ANSI C mallloc returned char *. That required an
explicit cast any time its return value was not assigned to a char *.
So, it is very likely that Kernighan was doing it out of habit.


It did indeed return a char *. And no, it did not require an explicit
cast any time its return value was not assigned to a char *. Pre-ANSI
C did not require casts on pointer assignments, the requirement came
with ANSI C.


A certain Dennis M. Ritchie seems to be thinking otherwise. From the
K&R2 errata (I've already posted the full quote):

On the other hand, pre-ANSI, the cast was necessary, and it is in
C++ also.

K&R1 explains the dangers of omitting the cast, at page 192.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #174
Richard Heathfield wrote:
when both sides are using
words like "idiot" and "nonsense". I dread to think what must be going
through the newbies' heads as they read your exchange with Mr Plauger.

We're loving it! Don't stop.

Nov 14 '05 #175
Dan Pop wrote:
In <bv**********@n ews.tudelft.nl> Sidney Cadot <si****@jigsaw. nl> writes:
Dan Pop wrote:
In <bv**********@n ews.tudelft.nl> Sidney Cadot <si****@jigsaw. nl> writes:

I know that in most contexts this isn't necessary because it will be
assigned to a typed pointer immediately after, but still it brings the
expressio n under the compiler's type checking regime a little bit
earlier, preventing such silliness as:

int *x = malloc(50*sizeo f(double));
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^
since

int *x = (double *)malloc(50*siz eof(double));
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
is an error.

Now I've seen all the counter-arguments to this by now, but in the end I
simply feel that malloc(50*sizeo f(double)) is incorrectly typed as
void*, and that's all there is to it as far as I am concerned.
In most cases, malloc(50*sizeo f(double)) is considered bad style.
Consider the alternative:

double *x = malloc(50 * sizeof *x);
That's funny, my lone expression seems to have turned into a full-blown
declarator/initializer as if by magic.

No magic at all: you have used it as such, in your own examples. Hence
my counterexample.


Ah, yes. I was trying to make a point about the expression
'malloc(50*size of(double))', but I can see where the confusion comes from.
My point, as you know by now but choose to ignore, is that the malloc
expression itself should be properly typed as a double*.


Nope, because it never used as an expression by itself: it's always used
either as an initialiser or as a subexpression of a wider expression
which establishes its intended type.

Unfortunately, all examples where the result of malloc() is not
immediately assigned (or something similar) look contrived, yes. That
doesn't invalidate the point. This fact-of-life is incidental, not
essential, for the purpose of this discussion.
Casting to double * not only doesn't add anything, because there is no
place left for the error you're talking about, but it is a maintenance
headache if the type of x ever needs to be changed, say to pointer
to long double: instead of making one change, you have to make two,


That's true. In fact, it's more of a "maintenanc e headache" than what
your preferred notation introduces when changing the identifier name
(but only slightly).


If you ever have to change identifier names in your code, there is
something very wrong with your coding methodology.


To me, that sounds like a bizarre statement. Please elaborate.
for no redeeming advantage.


The redeeming advantage, to me, is the knowledge that I have corrected
the misconception of the compiler about the type of an object at the
earliest possible opportunity. The compiler has no misconceptions about anything.


I disagree. Provided the malloc has succeeded, there is a bunch of
consecutive bytes floating around, intended to be used as a double
array. Such a bunch of bytes should properly be typed double *.

Unfortunately, the C language lacks a new operator that yields a
properly typed result. We have to make do with malloc, which has little
choice other than to return a void *. This constraint of the language
leads to the weird situation that a pointer to memory area that should
be properlt typed is not (yet) properly typed. I think it's right to
call this a misconception on the side of the compiler, and I think it's
right to correct this.
That way, I don't have to rely on the semantics of C with regard to
allowing void*-to-any* assignments, which I think are an ugly wart on
C's type safety system.


I'm afraid that few C programmers share your views.


I'm afraid you're right.
An analogy may help. Here in Holland, it aggrieves me to say, we have no
law forbidding the wearing of white socks under a suit. But that doesn't
mean I don't make an effort to avoid being dressed like that.


So, what kind of socks are you wearing under a white suit?


I have no idea. My analogy invertor comes up empty.

Best regards,

Sidney

Nov 14 '05 #176
Sidney Cadot wrote:
[...]
My point, as you know by now but choose to ignore, is that the malloc
expression itself should be properly typed as a double*.
[...]
The redeeming advantage, to me, is the knowledge that I have corrected
the misconception of the compiler about the type of an object at the
earliest possible opportunity.

That way, I don't have to rely on the semantics of C with regard to
allowing void*-to-any* assignments, which I think are an ugly wart on
C's type safety system.


Do you rely on the promotion rules? Do you think that the rules with
all the implicit conversions between signed/unsigned int types, float,
double, etc. for numbers provide more type safety than the void* to
any* conversions for pointers? Or do you always write something like
this:

char c = (char)((int)'0' + (int)9);

As I previously wrote far below in the thread, there are three
situations where, for a pointer d, the types of d and *d are relevant:

Assignment: d[10] = 5.3;
Read + arithmetics: a[5] = d[10] * 1.7;

Low level memory management including pointer arithmetic:
d = malloc(50 * sizeof(*d));
memcpy(&d[10], &a[5], 5 * sizeof(*d));
a = d + 10;

What happens when the types of d and a are changed to int*? The memory
functions will work perfectly without change, in fact the type does
not matter at all. For the above assignment and read, you will get an
unexpected result for a[5]. Do you care for it with casts? Caring for
the type where the language provides anything to completely abstract
it away, and not caring for it where it really matters is at least a
bit inconsequent, IMHO.
Holger
Nov 14 '05 #177
Holger Hasselbach wrote:
Sidney Cadot wrote:
[...]
My point, as you know by now but choose to ignore, is that the malloc
expression itself should be properly typed as a double*.
[...]
The redeeming advantage, to me, is the knowledge that I have corrected
the misconception of the compiler about the type of an object at the
earliest possible opportunity.

That way, I don't have to rely on the semantics of C with regard to
allowing void*-to-any* assignments, which I think are an ugly wart on
C's type safety system.

Do you rely on the promotion rules? Do you think that the rules with
all the implicit conversions between signed/unsigned int types, float,
double, etc. for numbers provide more type safety than the void* to
any* conversions for pointers? Or do you always write something like
this:

char c = (char)((int)'0' + (int)9);


I rely on the rules that I think are reasonable. This includes your
sample case (so I don't use casts there), and things like implicit
int-to-float conversion.

I do not rely on the rules that I think are unreasonable. This includes
implicit void*-to-any* conversions, but also implicit float-to-int
conversions.

So I would never write:

intVar = floatVar;

But I would always use an explicit cast (and only in cases where I do
not care too much about rounding).
As I previously wrote far below in the thread, there are three
situations where, for a pointer d, the types of d and *d are relevant:
Only three?
Assignment: d[10] = 5.3;
Read + arithmetics: a[5] = d[10] * 1.7;

Low level memory management including pointer arithmetic:
d = malloc(50 * sizeof(*d));
memcpy(&d[10], &a[5], 5 * sizeof(*d));
a = d + 10;

What happens when the types of d and a are changed to int*? The memory
functions will work perfectly without change, in fact the type does
not matter at all. For the above assignment and read, you will get an
unexpected result for a[5].
I think "unexpected " is a very subjective term... I do not think
anything would happen that I did not expect.
Do you care for it with casts?
As stated above, I make an effort to avoid implicit float-to-int
conversions.
Caring for
the type where the language provides anything to completely abstract
it away, and not caring for it where it really matters is at least a
bit inconsequent, IMHO.


Mastery of any subject is not about knowing the rules, but perhaps more
about good judgement about when to break them.

(Not that it applies of course, but it sounds quite profound)

Best regards,

Sidney

Nov 14 '05 #178
On Mon, 26 Jan 2004 22:54:26 GMT,
P.J. Plauger <pj*@dinkumware .com> wrote
in Msg. <CU************ ***@nwrddc01.gn ilink.net>
1) Style rules should be developed by considering all applicable
principles and weighing their various importance *for that particular
rule*.


So if you write a function that expects a void pointer but uses another
type internally (like the compare function for qsort), would you do it
like this?

int foo(void *a)
{
struct whatever_struct *s = (struct whatever_struct *) a;
/* ... */
}

--Daniel

--
"With me is nothing wrong! And with you?" (from r.a.m.p)
Nov 14 '05 #179
On Wed, 28 Jan 2004 18:49:52 +0000,
Tak-Shing Chan <es***@city.ac. uk> wrote
in Msg. <Pine.GSO.4.33. 0401281740480.1 8387-100000@swindon>
On Wed, 28 Jan 2004, Richard Bos wrote:
As for the third argument, it is demonstrably false; and has been shown
to be false repeatedly in this newsgroup.


AFAICT it has /not/ been shown false. The lack of malloc
casts could actually hide undefined behaviors:

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

double *x; /* Wrong declaration */

int
main(void)
{
x = (int *) malloc(sizeof *x);


When you start casting x here, why not cast it everywhere you use it? This
doesn't have to do with malloc().

--Daniel

--
"With me is nothing wrong! And with you?" (from r.a.m.p)
Nov 14 '05 #180

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

33
2300
by: hermit_crab67 | last post by:
Can someone explain to a C newbie why this doesn't work as I expect it to work? (expectations clearly outlined in the printf statement in main routine) OS: Linux 2.4.26 GCC: 2.95.4 void modify_pointer(char *); int main(int argc, char *argv) {
35
2721
by: ytrama | last post by:
Hi, I have read in one of old posting that don't cast of pointer which is returned by the malloc. I would like to know the reason. Thanks in advance, YTR
32
2403
by: alex.j.k2 | last post by:
Hello all, I have "PRECISION" defined in the preprocessor code and it could be int, float or double, but I do not know in the code what it is. Now if I want to assign zero to a "PRECISION" variable, which of the following lines are correct:
101
4381
by: Tinkertim | last post by:
Hi, I have often wondered if casting the return value of malloc() (or friends) actually helps anything, recent threads here suggest that it does not .. so I hope to find out. For instance : char *tmp = NULL;
0
9752
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11031
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10685
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10763
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10371
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7918
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5750
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5942
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
3188
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.