newsuser@oliver.SUBLINK.ORG (Ugo Cei) (05/07/91)
[This is crossposted to comp.lang.c, since the discussion on the pointer/integer relationship may have a wider audience than just Unix programmers.] From a typical SysV shmat(2) man page: | char *shmat (shmid, shmaddr, shmflg) | int shmid; | char *shmaddr; | int shmflg; [...] | Diagnostics | Upon successful completion, the return value is as follows: | | shmat returns the data segment start address of the | attached shared memory segment. | | shmdt returns a value of 0. | | Otherwise, a value of -1 is returned, and errno is set to | indicate the error. I have always believed that comparing pointers to integers was not portable, unless the integer is the constant 0 (which is not an integer at all, in this context). Well, if you concede me this, how am I supposed to test for the failure or success of shmat(2) ? Maybe: char * shmaddr; if((shmaddr = shmat(shmid, shmaddr, shmflg)) < 0) ... This, however, elicits a severe warning from my compiler, since I am not supposed to do an ordered comparison of a pointer and an integer. This is an issue that I wholeheartedly agree with. In the end, I have resorted to this kind of kludge: if((shmaddr = shmat(shmid, shmaddr, shmflg)) == (char *)(~0)) ... I know, this is not portable either, but my eyes are much more pleased since this resembles ``... == (char *) 0'', which IS portable. And even my compiler has stopped complaining. Now, my question is: why on earth wasn't shmat(2) made to return 0 (NULL) in case of failure ? Are there some subtle reasons for this that I am not aware of ? Inquiring mind wants to know. -- **************** | Ugo Cei | home: newsuser@oliver.sublink.org * OLIVER * | Via Colombo 7 | office: cei@ipvvis.unipv.it **************** | 27100 Pavia ITALY | "Real Programs Dump Core"
steve@taumet.com (Stephen Clamage) (05/08/91)
newsuser@oliver.SUBLINK.ORG (Ugo Cei) writes: >From a typical SysV shmat(2) man page: >| char *shmat (shmid, shmaddr, shmflg) ... >| Diagnostics >| ... >| Otherwise, a value of -1 is returned ... >I have always believed that comparing pointers to integers was not >portable, unless the integer is the constant 0 (which is not an >integer at all, in this context). Correct. The man page says that -1 is returned, not ~0, so just compare the return to -1, suitably cast: if((shmaddr = shmat(shmid, shmaddr, shmflg)) == (char *)(-1)) I would not be overly concerned with portability on this, since it is a Unix-specific issue. This code should work on any system supplying shmat. -- Steve Clamage, TauMetric Corp, steve@taumet.com
allbery@NCoast.ORG (Brandon S. Allbery KB8JRR/AA) (05/11/91)
As quoted from <986@oliver.SUBLINK.ORG> by newsuser@oliver.SUBLINK.ORG (Ugo Cei): +--------------- | I know, this is not portable either, but my eyes are much more pleased | since this resembles ``... == (char *) 0'', which IS portable. And | even my compiler has stopped complaining. Now, my question is: why on | earth wasn't shmat(2) made to return 0 (NULL) in case of failure ? Are | there some subtle reasons for this that I am not aware of ? +--------------- Not so subtle: ALL system calls return -1 on failure. No exceptions. This is generally handled by assembly language glue in libc.a (the versions of Unix whose assembler calling conventions I'm familiar with set the "carry" flag to indicate an error on return from a system call). In any case, the return value from shmat() is not "portable" anyway, because I may not want a (char *). I have a program which uses it as a (double *), for example. Now, as it turns out, alignment is guaranteed by the default calling sequence (you can pass flags to shmat() which can affect this, but the default is suitably aligned for any type), but it's notoriously difficult to explain this to C, which is why (void *) was invented. ++Brandon -- Me: Brandon S. Allbery Ham: KB8JRR/AA 10m,6m,2m,220,440,1.2 Internet: allbery@NCoast.ORG (restricted HF at present) Delphi: ALLBERY AMPR: kb8jrr.AmPR.ORG [44.70.4.88] uunet!usenet.ins.cwru.edu!ncoast!allbery KB8JRR @ WA8BXN.OH