wrd3156@fedeva.UUCP (Bill Daniels) (05/03/88)
How do I cast the malloc() in line 12 of the following program to avoid the lint cries of "warning: illegal pointer combination" et al? My system is a Perkin-Elmer 3210 running SYS V rel. 2. I have tried "all but one" of every combination of casts known to mankind. Help me find the only one left, the one that works! #include <stdio.h> main() { char *malloc(); int i; struct outfile { int j; int k; } (*output)[]; output = malloc(sizeof(struct outfile) * 3); (*output)[0].j = 1; (*output)[0].k = 2; i = printf("%d %d\n",(*output)[0].j,(*output)[0].k); return(i); } THIS IS MY LINT'S OUTPUT: trial.c ============== warning: illegal pointer combination (12) warning: possible pointer alignment problem (12) Thanks for any assistance! -- bill daniels federal express, memphis, tn {hplabs!csun,gatech!emcard}!fedeva!wrd3156
friedl@vsi.UUCP (Stephen J. Friedl) (05/03/88)
In article <294@fedeva.UUCP>, wrd3156@fedeva.UUCP (Bill Daniels) writes: > > [nonessential lines deleted here] > > How do I cast the malloc() in line 12 of the following program to avoid > the lint cries of "warning: illegal pointer combination" et al? > > main() > { > char *malloc(); > > struct outfile { > int j; > int k; > } (*output)[]; > > output = malloc(sizeof(struct outfile) * 3); Some casts defy obvious attempts, and this is one of them. First, declare an abstract variable (I always use "foo") of the same type you want to cast. We want to say "foo is a pointer to an array of struct outfile", so it would be: struct outfile (*foo)[] This is just an ordinary variable, and it's the same declaration as "output" above. To turn this into a cast, drop the "foo" and put parens around the whole thing: (struct outfile (*)[]) ^^_________ foo *was* between here This is the "obvious" proper cast. Think how this works on others: the variable is... abstract decl cast ------------------ ------------- -------- int int foo (int) ptr to char char *foo (char *) ptr to fcn rtn int int (*foo)() (int (*)()) In any valid cast, there is exactly one place where the abstract variable would fit, and after a while you can get the hang of where it goes. -- Steve Friedl V-Systems, Inc. (714) 545-6442 3B2-kind-of-guy friedl@vsi.com {backbones}!vsi.com!friedl attmail!vsi!friedl
ajmyrvold@violet.waterloo.edu (Alan Myrvold) (05/03/88)
In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: > >How do I cast the malloc() in line 12 of the following program to avoid >the lint cries of "warning: illegal pointer combination" et al? ... > struct outfile { > int j; > int k; > } (*output)[]; > > output = malloc(sizeof(struct outfile) * 3); Did you try : output = (struct outfile **) malloc(sizeof(struct outfile) * 3); This goes through lint here, althougth lint complains that sizeof(struct outfile) * 3 is long, and should be unsigned. So output = (struct outfile **) malloc((unsigned) sizeof(struct outfile) * 3); should clear everything up. ------------------------------------------------------------------- Si je t'aime? Bien sur que je t'aime! Ne suis-je pas en train de te le prouver encore une fois, dans ce lit? ------------------------------------------------------------------- Alan Myrvold ajmyrvold@violet.waterloo.edu -------------------------------------------------------------------
gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/03/88)
In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: >How do I cast the malloc() in line 12 of the following program to avoid >the lint cries of "warning: illegal pointer combination" et al? General, SVR2 "lint" will complain about casting the (char *) returned by malloc() into other pointer types, and there seems to be no way around it. The best you can do is obtain a "possible pointer alignment problem" warning. That's because "lint" does not know that the pointer returned by malloc() is guaranteed to point to properly aligned storage for any use.
chris@mimsy.UUCP (Chris Torek) (05/03/88)
In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: > char *malloc(); > struct outfile { > int j; > int k; > } (*output)[]; > output = malloc(sizeof(struct outfile) * 3); First, note that output is not a proper variable: % echo 'declare output as pointer to array of struct outfile' | cdecl Warning: Unsupported in C -- Pointer to array of unspecified dimension struct outfile (*output)[] % In particular, your compiler will let you write (*output)[i], or output[0][i], but try output[j][i] and <boom>! I have argued this point here before; I will only say now that this is not what C wants you to say to create a dynamic array 3 of struct outfile: you should be using a simple pointer. Nonetheless, it happens to work. On to the cast: The syntax of a cast is exactly the same as the syntax of a declaration, minus the variable name. Hence to cast malloc to the same (unsupported) type: output = (struct outfile (*)[])malloc(...); -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
hender@prandtl.nas.nasa.gov.nas.nasa.gov (Bob Henderson) (05/04/88)
In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: > >How do I cast the malloc() in line 12 of the following program to avoid >the lint cries of "warning: illegal pointer combination" et al? >My system is a Perkin-Elmer 3210 running SYS V rel. 2. I have tried >"all but one" of every combination of casts known to mankind. Help me find >the only one left, the one that works! >... Lint is complaining about the assignmemt, not because of the casting, but because it is not sure the byte address returned by malloc will allign the structure correctly. (It most likely will, but link cannot be sure). So the "trick" is to force the alignment to a word boundry. Assuming that "int" is the natural size for your machine; you might code the cast like: struct foo { long count; char byte; int junk; } foo, *pfoo; char *malloc(), *cp; /* step 1: allocate n-1 extra bytes for alignment */ cp = malloc(sizeof(foo)+sizeof(int)-1); /* step 2: align address to natural boundry */ pfoo = (struct foo *)(( (int)cp +sizeof(int)-1) & ~(sizeof(int)-1) ); In step 1, the space is allocated, along with extra space for the allignment. In step 2, the address malloc returned (a byte address) is adjusted to point to the next byte address (inclusive) that is also a int address. If double words or some large address type is involved, then use that type instead of int. ----------------------------------------------------------------------------- Bob Henderson NASA Ames Research Center arpa: hender@prandtl.nas.nasa.gov uucp: {ihnp4,hplabs,ucbcad,tektronix,allegra}!ames!prandtl!hender "I like work; it fascinates me; I can sit and look at it for hours."
carlp@iscuva.ISCS.COM (Carl Paukstis) (05/04/88)
In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: = =How do I cast the malloc() in line 12 of the following program to avoid =the lint cries of "warning: illegal pointer combination" et al? = =#include <stdio.h> = =main() ={ = char *malloc(); = int i; = struct outfile { = int j; = int k; = } (*output)[]; = = output = malloc(sizeof(struct outfile) * 3); = = (*output)[0].j = 1; = (*output)[0].k = 2; = = i = printf("%d %d\n",(*output)[0].j,(*output)[0].k); = = return(i); =} =-- =bill daniels =federal express, memphis, tn ={hplabs!csun,gatech!emcard}!fedeva!wrd3156 output = (struct outfile **)malloc(sizeof(struct outfile) * 3); works on Ultrix 2.something, a Sys V "compliant" type system complains of "possible pointer alignment problem", presumably because "char" requires only byte alignment (returned from malloc), while "struct outfile *" requires halfword alignment (on 68010 systems). Maybe my lint is too good... I can't find a combination that passes clean on the Sys V system, either. -- Carl Paukstis +1 509 927 5600 x5321 |"I met a girl who sang the blues | and asked her for some happy news UUCP: carlp@iscuvc.ISCS.COM | but she just smiled and turned away" ...uunet!iscuva!iscuvc!carlp | - Don MacLean
limes@sun.uucp (Greg Limes) (05/04/88)
In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: >How do I cast the malloc() in line 12 of the following program to avoid >the lint cries of "warning: illegal pointer combination" et al? > > >#include <stdio.h> > >main() >{ > char *malloc(); > int i; > struct outfile { > int j; > int k; > } (*output)[]; > > output = malloc(sizeof(struct outfile) * 3); > > (*output)[0].j = 1; > (*output)[0].k = 2; > > i = printf("%d %d\n",(*output)[0].j,(*output)[0].k); > > return(i); >} Several quick points: 1) this looks like a job for typedef; if its too complex to figure out the cast, it may be too complex to read the cast. A translation of your code literally into typedefs gives the following results for declaration and cast: typedef struct { int j, k; } outrec; typedef outrec outfile[]; outfile *output; output = (outfile *) malloc (3 * sizeof (outrec)); 2) Pointers to indefinite sized arrays are normally kept simply as a pointer to the beginning of the array. This removes one level of indirection in the code, making it easier to read: all your "(*ptr)[rec].field" constructs change into "ptr[rec].field", giving somewhat easier to write, read, and maintain code. Expanding your program a bit shows one way of using this: /* sortecho: echo parameters, sorted shortest first */ char *malloc (); typedef struct { int len; char *ap; } outrec; int cmp_rec (p, q) outrec *p, *q; { return p->len - q->len; } main (ac, av) char **av; { int nrec; outrec *output; nrec = ac - 1; output = (outrec *) malloc (nrec * sizeof (outrec)); for (i = 0; i < nrec; ++i) { output[i].ptr = av[i + 1]; output[i].len = strlen (av[i + 1]); } qsort (output, nrec, sizeof (outrec), cmp_rec); for (i = 0; i < nrec; ++i) printf ("%6d: %s\n", output[i].len, output[i].ptr); } -- Greg Limes [limes@sun.com] Illigitimi Non Carborundum
chris@mimsy.UUCP (Chris Torek) (05/04/88)
In article <51875@sun.uucp> limes@sun.uucp (Greg Limes) writes: >2) Pointers to indefinite sized arrays are normally kept simply as a > pointer to the beginning of the array. This removes one level of > indirection in the code, making it easier to read: all your > "(*ptr)[rec].field" constructs change into "ptr[rec].field", giving > somewhat easier to write, read, and maintain code. I would (indeed, I did) put it more strongly: it makes it correct. This is the right idea, in any case. There are some who claim that (*p)[i] is somehow more indicative that there is an indefinitely sized array around somewhere, but I disagree, and side with Greg: p[i] is clearer. One small fix: > typedef struct { int len; char *ap; } outrec; > int cmp_rec (p, q) outrec *p, *q; { return p->len - q->len; } ... > qsort (output, nrec, sizeof (outrec), cmp_rec); A shiny new dpANS-conformant compiler will complain here, if you have written a `#include <stddef.h>' as well, for qsort's final argument is not a function with two structure pointer arguments, but rather a function with two (char *) or (void *) arguments (depending on who you ask: K&R 1st ed., or dpANS). int cmp_rec(p, q) char *p, *q; { return (((outrec *)p)->len - ((outrec *)q)->len); } If you do otherwise, on a DG MV series machine, your code will work about as well as the 4.3BSD `ls' does---which is to say, not at all. (The Data General has Word Pointers and Byte Pointers, and never the twain should meet, save by a Cast.) (And if we *really* get picky we can worry about the call to malloc when nrec==0. :-) ) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
walter@hpcllz2.HP.COM (Walter Murray) (05/04/88)
Bill Daniels writes: > How do I cast the malloc() in the following program to avoid > the lint cries of "warning: illegal pointer combination" et al? [program abbreviated] > #include <stdio.h> > main() > { > char *malloc(); > struct outfile { > int j; > int k; > } (*output)[]; > output = malloc(sizeof(struct outfile) * 3); > } > THIS IS MY LINT'S OUTPUT: > trial.c > ============== > warning: illegal pointer combination > (12) > warning: possible pointer alignment problem > (12) To avoid the "illegal pointer combination", try: output = (struct outfile (*)[])malloc(sizeof(struct outfile) * 3); The "possible pointer alignment problem" warning comes from the fact that malloc(3) is declared to return char*, even though we know that the alignment of its return pointer is such that it can be used for anything. To get rid of that warning, try: output = (struct outfile (*)[])(int)malloc(sizeof(struct outfile) * 3); Conversions of pointers to integral types and back are implementation- defined, but this should work if int on your machine is wide enough to hold a pointer. If not, try long instead. --Walter Murray
lmiller@venera.isi.edu (Larry Miller) (05/04/88)
In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: > >How do I cast the malloc() in line 12 of the following program to avoid >the lint cries of "warning: illegal pointer combination" et al? > >main() >{ > char *malloc(); > int i; > struct outfile { > int j; > int k; > } (*output)[]; > > output = malloc(sizeof(struct outfile) * 3); Probably seen 100s of these by now, but here goes: % cdecl cast malloc into pointer to array of struct outfile Warning: Unsupported in C -- Pointer to array of unspecified dimension (struct outfile (*)[])malloc(sizeof(struct outfile) * 3); NOTE the warning!! And note that the cast is almost the same as the definition of output, only the name is removed. Larry Miller lmiller@venera.isi.edu (no uucp) USC/ISI 213-822-1511 4676 Admiralty Way Marina del Rey, CA. 90292
henry@utzoo.uucp (Henry Spencer) (05/05/88)
> Lint is complaining about the assignmemt, not because of the casting, but > because it is not sure the byte address returned by malloc will allign the > structure correctly. (It most likely will, but link cannot be sure). Malloc in fact is required to, so there is no need for elaborate measures to ensure it. The problem is that lint does not know that malloc does in fact guarantee alignment. -- NASA is to spaceflight as | Henry Spencer @ U of Toronto Zoology the Post Office is to mail. | {ihnp4,decvax,uunet!mnetor}!utzoo!henry
njk@diku.dk (Niels J|rgen Kruse) (05/05/88)
In article <7822@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes: > In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: > >How do I cast the malloc() in line 12 of the following program to avoid > >the lint cries of "warning: illegal pointer combination" et al? > (..) > it. The best you can do is obtain a "possible pointer alignment problem" > warning. That's because "lint" does not know that the pointer returned by > malloc() is guaranteed to point to properly aligned storage for any use. ^^^^^^^^^^^^^^^^ I have been wondering why malloc() returns a (char *), when it is guaranteed to satisfy all alignment requirements. It would seem to be more proper to return (maxalign *), where maxalign is a type with the strictest alignment requirements of all types. This would inform lint that the cast is safe. In addition, passing (char *) is inefficient on some architectures, whereas passing (maxalign *) would be efficient on all architectures. I dont know anything about ANSI-C, other than what i have picked up in this newsgroup. I gather that malloc has been redefined as void *malloc(). Is a (void *) guaranteed to satisfy all alignment requirements? If so i would hope that this is reflected in the representation, so that passing a (void *) is the most efficient way to pass a pointer. Changing declarations of malloc in existing code would be a small price to pay for getting this cleaned up. Niels J|rgen Kruse stud. scient. at DIKU. (DIKU ~= CS dept. of University of Copenhagen)
jfh@rpp386.UUCP (John F. Haugh II) (05/06/88)
In article <7822@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <294@fedeva.UUCP> wrd3156@fedeva.UUCP (Bill Daniels) writes: >>How do I cast the malloc() in line 12 of the following program to avoid >>the lint cries of "warning: illegal pointer combination" et al? > >General, SVR2 "lint" will complain about casting the (char *) returned >by malloc() into other pointer types, and there seems to be no way around >it. my answer didn't make it out due to hardware trouble. however, while banging on the problem i tried solving the lint noise. what i learned was that if i declared void *malloc (); then lint shut up. this would seem to be the correct behavior for an ANSI conforming lint. i did get errors concerning the use of malloc, but those could be corrected by properly declaring malloc (as above) in llib-c. well, karl, what you got to say??? - john. -- John F. Haugh II | "You see, I want a lot. Perhaps I want every River Parishes Programming | -thing. The darkness that comes with every UUCP: ihnp4!killer!rpp386!jfh | infinite fall and the shivering blaze of DOMAIN: jfh@rpp386 | every step up ..." -- Rainer Maria Rilke
henry@utzoo.uucp (Henry Spencer) (05/06/88)
> I have been wondering why malloc() returns a (char *), when > it is guaranteed to satisfy all alignment requirements. It > would seem to be more proper to return (maxalign *), where > maxalign is a type with the strictest alignment requirements of > all types. This would inform lint that the cast is safe. If you accept the need to cast all results of malloc, there is nothing inherently very wrong with this. Note, however, that the type of maxalign is implementation-dependent. On some systems I'm not sure, actually, that there is a specific type that expresses the maximal alignment constraint. (Since I carefully avoid these silly machines that have segments, I'm not intimate with the details of their flaws.) > ...redefined as void *malloc(). Is a (void *) guaranteed to > satisfy all alignment requirements? No. A "void *" is guaranteed to be able to hold any other pointer intact. (Well, any other data pointer.) This means that it has pretty much the same characteristics as "char *", and in fact I think it is required to use the same representation. The purpose of "void *" is to be a real, true pointer-to-anything, so that "char *" can go back to being specifically pointer-to-char. The properties of "void *" are also defined in such a way that many conversions between it and other pointer representations do not require explicit casts. There is still no fully portable way to say "maximally aligned pointer". If somebody wants to implement one and try it out, the next incarnation of X3J11 would probably be interested in hearing about it when the time comes to revise the C standard, several years from now. I don't think there is any actual implementation experience to justify trying to put it in now. I'm not even quite sure how I would add this to the language: one wants something that shares "void *"'s property of not needing explicit casts, while also being maximally aligned (which may not be expressible as an ordinary C type). Perhaps "struct *"? (Ugh.) -- NASA is to spaceflight as | Henry Spencer @ U of Toronto Zoology the Post Office is to mail. | {ihnp4,decvax,uunet!mnetor}!utzoo!henry
pedersen@acf3.NYU.EDU (paul pedersen) (05/06/88)
Walter Murray writes:
<The "possible pointer alignment problem" warning comes from the
<fact that malloc(3) is declared to return char*, even though we
<know that the alignment of its return pointer is such that it can
<be used for anything. To get rid of that warning, try:
<
< output = (struct outfile (*)[])(int)malloc(sizeof(struct outfile) * 3);
<
<Conversions of pointers to integral types and back are implementation-
<defined, but this should work if int on your machine is wide enough
<to hold a pointer. If not, try long instead.
This is terrible, outrageous, and disgusting. In order to get 'lint' to
shut up, this mechanism sacrifices portability! The whole point of running
'lint' in the first place is to detect constructions that may work but are
not portable (I know there are other reasons for 'lint'-ing, but this is
the >primary< reason).
Better just to eat the lint complaints automatically with grep -v, as someone
else has already suggested.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/07/88)
In article <3802@diku.dk> njk@diku.dk (Niels J|rgen Kruse) writes: >... I gather that malloc has been redefined as void *malloc(). >Is a (void *) guaranteed to satisfy all alignment requirements? No. There are two distinct properties of the pointer returned by malloc(): one is that it is a "generic" pointer, capable of being safely converted to a pointer to any object type; the other is that it is guaranteed to be properly aligned so that this conversion is meaningful. These two properties are NOT the same and should not be bundled into a single language element. The "super-aligned" property is only true of pointers returned by malloc() and therefore didn't seem to need a specific notion in the C language. The "generic" property is essentially what ANSI C "void *" is intended for.
ok@quintus.UUCP (Richard A. O'Keefe) (05/07/88)
In article <691@acf3.NYU.EDU>, pedersen@acf3.NYU.EDU (paul pedersen) writes: > Better just to eat the lint complaints automatically with grep -v, as someone > else has already suggested. There is a slightly better way still. #ifdef lint #define Malloc(Type,Amount) ((void)malloc(Amount), (Type)(0)) #else #define Malloc(Type,Amount) (Type)malloc(Amount) #endif #define Talloc(Type) Malloc(Type*,sizeof (Type)) typedef ..... Thing; Thing *p; p = Talloc(Thing); lint #defines lint, so lint will see p = ((void)malloc(sizeof (Thing)), (Thing*)(0)); but the C compiler will see p = (Thing*)malloc(sizeof (Thing)); This shuts lint up about _only_ pointer alignment problems involving malloc(), which is what you really want, as the others may be genuine. When you find other generic cases, you can fix them the same way. That's what #ifdef lint is for! Another common use for #ifdef lint is for things like #ifndef lint static char copyr[] = "@(#)Copyright (C) 1988 Muppet Labs, Incorporated."; #endif where lint would complain about copyr not being used.
thorinn@diku.dk (Lars Henrik Mathiesen) (05/11/88)
In article <1988May6.165221.536@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >There is still no fully portable way to say "maximally aligned pointer". >... >I'm not even quite sure how I would add this to the language: one wants >something that shares "void *"'s property of not needing explicit casts, >while also being maximally aligned (which may not be expressible as an >ordinary C type). Perhaps "struct *"? (Ugh.) How about some `prior art' : teach lint about /*MAXALIGN*/, it knows about so many special cases already. After all, it's not a language feature, it's a feature of malloc(), so llib-lc is a good place for the information. The next problem is with compiler writers who insist on warning about such things on compilation. They will have to put in support for /*MAXALIGN*/, and put that in <malloc.h> (if it exists). Or use a #pragma. Or their users will have to live with the warnings (most probable?). -- Lars Mathiesen, DIKU, U of Copenhagen, Denmark [uunet!]mcvax!diku!thorinn Institute of Datalogy -- we're scientists, not engineers.
karl@haddock.ISC.COM (Karl Heuer) (05/14/88)
In article <3817@diku.dk> thorinn@diku.dk (Lars Henrik Mathiesen) writes: >The next problem is with compiler writers who insist on warning about >[possible alignment problems] on compilation. They will have to put in >support for /*MAXALIGN*/... Or use a #pragma. Or their users will have to >live with the warnings (most probable?). If they're going to add the warning message, they'd better make damn sure that "int *ip = (int *)malloc(sizeof(int));", which is perfectly valid, not produce the warning. "Live with the warnings" is unacceptable. If it's true that #pragma is not allowed to change the semantics of a program, then this may be an excellent example of what it *is* good for. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint