From owner-freebsd-questions@FreeBSD.ORG Fri Aug 19 11:43:22 2005 Return-Path: X-Original-To: freebsd-questions@freebsd.org Delivered-To: freebsd-questions@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7806A16A41F for ; Fri, 19 Aug 2005 11:43:22 +0000 (GMT) (envelope-from keramida@ceid.upatras.gr) Received: from kane.otenet.gr (kane.otenet.gr [195.170.0.95]) by mx1.FreeBSD.org (Postfix) with ESMTP id BC8D343D45 for ; Fri, 19 Aug 2005 11:43:21 +0000 (GMT) (envelope-from keramida@ceid.upatras.gr) Received: from flame.pc (aris.bedc.ondsl.gr [62.103.39.226]) by kane.otenet.gr (8.13.4/8.13.4/Debian-1) with SMTP id j7JBhKEL016107; Fri, 19 Aug 2005 14:43:20 +0300 Received: from flame.pc (flame [127.0.0.1]) by flame.pc (8.13.4/8.13.4) with ESMTP id j7JBhIfe002943; Fri, 19 Aug 2005 14:43:18 +0300 (EEST) (envelope-from keramida@ceid.upatras.gr) Received: (from keramida@localhost) by flame.pc (8.13.4/8.13.4/Submit) id j7JBhHR0002942; Fri, 19 Aug 2005 14:43:17 +0300 (EEST) (envelope-from keramida@ceid.upatras.gr) Date: Fri, 19 Aug 2005 14:43:17 +0300 From: Giorgos Keramidas To: Dmitry Mityugov Message-ID: <20050819114317.GA2675@flame.pc> References: <4303A632.1000809@FreeBSD.org> <4303B016.3030201@mac.com> <43044212.20909@FreeBSD.org> <20050818125348.GG1282@flame.pc> <20050818214003.GA687@flame.pc> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Cc: freebsd-questions@freebsd.org Subject: Re: man malloc X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Aug 2005 11:43:22 -0000 On 2005-08-19 15:00, Dmitry Mityugov wrote: >On 8/19/05, Giorgos Keramidas wrote: >>On 2005-08-18 22:17, Dmitry Mityugov wrote: >>>On 8/18/05, Giorgos Keramidas wrote: >>>> It may be surprising, but casting back and forth *MAY* change the >>>> value of the pointer. >>>> ... >>> >>> Could you back up this assertion with an example, please? >> >> Do I really have to? >> ... > > I just wanted to learn something new. Please, post an example if you can. There is an easy to reproduce case, when running executables of certain "memory models" in MS-DOS. Many users forget that function pointers are *NOT* the same as object pointers. They generally happen to "just work" on most UNIX machines, but they are not the same at all. For instance, this will tend to work on FreeBSD: 1 #include 2 #include 3 #include 4 5 static int increase(int *); 6 static int decrease(int *); 7 8 typedef int (*fptr_t)(int *); 9 10 int 11 main(void) 12 { 13 int k, oval, val; 14 char *p[] = { (char *)increase, (char *)decrease, }; 15 fptr_t fptr; 16 17 val = 0; 18 for (k = 0; k < 10; k++) { 19 fptr = (fptr_t)(p[rand() % 2]); 20 oval = fptr(&val); 21 printf("%3d -> %3d\n", oval, val); 22 } 23 return (0); 24 } 25 26 int 27 increase(int *xp) 28 { 29 int old; 30 31 assert(xp != NULL); 32 old = *xp; 33 *xp += 1; 34 return (old); 35 } 36 37 int 38 decrease(int *xp) 39 { 40 int old; 41 42 assert(xp != NULL); 43 old = *xp; 44 *xp -= 1; 45 return (old); 46 } On most UNIX installations I've seen, the (char *) pointers at line 14 can save the address of a function, even though this is not allowed by the C standard. If you build this with GCC using the -std=c89 -pedantic options, a warning *IS* printed both for the dubious casts of function pointers to (char *) in line 14 and for the cast back to a function pointer (simplified a bit through a typedef) at line 19: % foo.c: In function `main': % foo.c:14: warning: ISO C forbids conversion of function pointer to object pointer type % foo.c:14: warning: ISO C forbids conversion of function pointer to object pointer type % foo.c:19: warning: ISO C forbids conversion of object pointer to function pointer type Having said that this is *NOT* standard C, now I can tell you why this may bite you in bad ways on some environments, even though it just happens to work on FreeBSD, Linux and Solaris, if you build the program without all the warnings of -std=c89. When programming with certain "memory models" in DOS though, you may find that a pointer to a function requires 32 bits of storage, while a pointer to the data area of the program requires only 16 (because, for instance, the program has a very large code area but it has only one 65 KB segment for storing data). In that case, a function pointer that is "coerced" into a (char *) may end up being trimmed. When you "coerce" it back to a function pointer it will almost certainly point to the wrong place. That's not very good. - Giorgos