Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!ames!lll-winken!uunet!crdgw1!steinmetz!davidsen From: davidsen@steinmetz.ge.com (Wm. E. Davidsen Jr) Newsgroups: comp.lang.c Subject: Re: When is a cast not a cast? Message-ID: <13721@steinmetz.ge.com> Date: 2 May 89 13:08:38 GMT References: <2747@buengc.BU.EDU> Reply-To: davidsen@crdos1.UUCP (bill davidsen) Organization: General Electric CRD, Schenectady, NY Lines: 75 In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes: | I wanted to be a 'good little programmer' and make all the types | match up, so I was using casts wherever a promotion might be | non-obvious. In particular, I fell for: (the line numbers are shown | only for reference) | | 1 main() | 2 { | 3 char *c; | 4 char *p; | 5 int i; | 6 ... | 7 c = "somestring"; /* Nothing fancy, null-terminated. */ | 8 i = 4; /* For example. */ | 9 ... | 10 p = (c + (char *) i); /* More trouble than it's worth... */ | 11 ... | 12 } | | wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with | warnings that the 'operands of + have incompatible types' on line 10... C allows expressions involving a pointer and an int. The expression ptr + int has the same type as ptr, and the address "ptr plus (int times the size of the base type of ptr). The following expressions refer to the same location, using the declarations at the start of the example: /* declare */ int *ptr; /* this is our pointer */ int m; /* this is the int we add */ int *value; /* this holds the resulting address */ /* these result in the same value */ value = (ptr + m); /* parens optional */ value = &ptr[m]; value = &m[ptr]; /* ugly and confusing, but legal */ In addition to the result of adding (or subtracting) an int and pointer, the result of subtracting two pointers is an int, the number of items of the base type of the pointers, subject to the following: a) the pointers must be of the same type b) the pointers must be into the same data structure or the results will not be portable (and may not work at all in some implementations). For example: int p[20], *ptr1, *ptr2, value; ptr1 = &p[0]; ptr2 = &p[4]; value = ptr2 - ptr1; /* always 4 */ regardless of the sizeof(int), the resul;t is four, because it is the *number of items* of the base type between the pointers. Changing the 'int' type to any other type, including struct and union types, will not effect the value of the subtraction. This eliminates some of the address arithmetic tricks required by older languages. The reason that you are getting errors is that you are trying to add two pointers, which is not a defined operation. Looking at your original code again, | 10 p = (c + (char *) i); /* More trouble than it's worth... */ what you want is just p = c + i; /* no trouble at all */ Hope I made this clear, it's harder to understand once you learn it wrong... I'm sure the usual people who respond to every question will reply to this one. -- bill davidsen (wedu@crd.GE.COM) {uunet | philabs}!steinmetz!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me