CompuServe Thread

#Lost at C (Again!)

22 messages in this thread
#59306From: Richard Rae/SYSOPMar 17, 1987 5:35 PM
Okay, all you C worthies… I need your help (again!), this time with interpreting something in the Manx manual (nope, I'm still using 3.20A just like everyone else). My problem is with the synopsis for localtime(), which is: struct tm *localtime(clock) long *clock; This says to me that localtime is a function returning type pointer-to-struct tm, and is called with one parameter which is of type pointer-to-long. My difficulty is in understanding where the struct comes in. In other words, I pass localtime() the address of a long which contains time in an internal format. localtime() returns to me a pointer to the structure containing the reformatted time. Eh? But I didn't tell the function what structure I wanted the data IN! Did it just pick one at random? I've tried all the things which look reasonable (and, in desperation, unreasonable), and Ami for the most part responded by crashing enthusiastically and often… just what I'd expect. So, I'd appreciate help with how to use this function. I couldn't find any code in the DL which uses anything similar. Best bet would be to give me a snippet of code showing how to do it, but anything would be appreciated. The next message will be the last code fragment I tried, which of course returns garbage, because the system and I aren't talking about the same structs. TNX 1E6!
#59307From: Richard Rae/SYSOPMar 17, 1987 5:36 PM
#include <time.h> main() { long value; struct tm time_struct; /* time_struct is of type struct tm */ struct tm *pointer; /* pointer is of type pointer to type struct tm */ value=time(); /* This call returns a long int time in internal form */ printf("%ld\n",value); pointer=localtime(&value); /* Call w/addr of value, return ptr to struct */ printf("%d %d",time_struct.tm_sec,time_struct.tm_min); }
#59314From: Don Curtis/SYSOPMar 17, 1987 6:08 PM
Rick, I'm not at home, so can't look up any of this, but off the top of my head (which could be in never never land also) I'd say you haven't bothered equating pointer to anything and thus haven't filled out time_struct. Try this before your printf() call: time_struct.tm_sec = pointer->tm_sec; time_struct.tm_min = pointer->tm_min; or time_struct.tm_sec = localtime(&value)->tm_sec; time_struct.tm_min = localtime(&value)->tm_min; In otherwords, you've created a pointer to a structure, but haven't equated the values within that structure to your structure. Also, I suspect that localtime() uses a temporary structure and the 2nd set of code may be more proper. Don
#59327From: Richard Rae/SYSOPMar 17, 1987 7:12 PM
Don, Sonofagun, that seems to have done the trick; at least, seconds are correct at this point. I'll not know until I get farther in testing, but I wanted to get back to you ASAP. A couple of observations/questions: I am encouraged to see that I apparently did everything "right", or at least acceptably, and my only barrier was not understanding the synopsis of the function. I was positive my code was munged, pointers where I should be using addresses, etc. I don't see the rationale behind doing it this way. If I were writing localtime(), I would have used localtime(inptime,strptr), where strptr would point to _your_ pre-existing tm structure. Care to comment on what I'm missing? Is the whole point to minimize the number of parms passed, or is it just a different strokes situation? I tried your first format, pointer->element. Since localtime() is returning the pointer to its struct, I see no reason not to use pointer in this manner. Would you mind explaining why you think the second method might be more proper for the temp structure? Is it because you are expecting the struct to go away, or the address to change, and that this would not be reflected in pointer? If I'm just going to scarf the numbers I need from the translation, is there any need to even bother with my struct? Seems I could just use the temp struct, as long as I don't call localtime() again. Thanks for bearing with the questions. I am still very much a novice C hack, and like to get these things straight in my mind for future use. Appreciate the rescue! Rick
#59342From: Don Curtis/SYSOPMar 17, 1987 8:27 PM
Rick, As to why localtime() is a pointer rather than a void accepting the pointer to a tm struct as one of it's arguments—I don't know, other than that's the way it was written. I can envision a few reasons why…perhaps you want to fill out several tm structs and a single call is sufficient, perhaps you only want to grab the minutes value and don't want to carry even a local structure around (saves memory) so you just use minutes = localtime(&clock)->tm_min; and you're done with it. More than likely, it's faster that way also. I suggested the second method as it will always be correct, but in your instant case, either is correct. Again, I presume a temporary structure is set up in memory which localtime() points to…local to that particular module only. If you had pointer as a global variable and attempted to use it in another module (or perhaps even in another function) you might get wrong results. Again, this presupposes that a local structure is created a pointer to it being returned via localtime(). Now, if localtime() returns a pointer to the system structure…the one that is always there running under AmigaDOS, then the use of pointer is correct. You grab the address of the system structure once, and from there on use indirect reference to it via pointer->element. I don't know if this is a dynamic structure (that is, if the values in it change as time changes), but if that is the case, then the fact that localtime() returns a pointer to it, makes absolute sense. It would then "find" the system structure, and from there on, you'd refer to via indirection and always have the correct time and could update an on-screen clock (or whatever) based on the value changing once a minute. Don
#59358From: Richard Rae/SYSOPMar 17, 1987 10:39 PM
Don, Thanks for the answers (and conjecture). If I get some spare time I'll hink around with it and let you know if the struct is temporary or system, and if it is static or dynamic. Now, here's YAP (Yet Another Problem)… I give up… I _KNOW_ this has come up time and again, but I can't find any of my references now: Where the heck is IntuitionBase? I've included everything I can think of, but the linker still isn't satisfied. Think I'll do the same thing here I did on the development system at work: make an include file called kitchen_sink which includes _ALL_ other include files; then I can just #include kitchen_sink and be done with it! 8) Seriously, though… where's IntuitionBase kept? Rick <Not quite getting C sick yet> Rae
#59362From: John DraperMar 17, 1987 11:15 PM
Ahhh… I can't tell you how to reference it via C, or how to "include" it, but I can tell you where it is. It starts at the address of the Intuition library base pointer. ie. When you OpenLibrary, the return value is Intuitionbase (provided that you opened the Intuition library of course). Regards, Larry.
#59366From: Richard Rae/SYSOPMar 17, 1987 11:24 PM
Lessee… That would be… IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",LIBRARY_VERSION); Nothing to it. 😉 Rick
#59398From: John DraperMar 18, 1987 4:40 AM
No? Then why are you multiplying Intuitionbase by nothing? <grin> I (foolsihe person that I am, just bought Gimpel's lint for the AMiga today. Maybe it will help me to decipher some of this strange looking stuff. Regards, Larry.
#59419From: Richard Rae/SYSOPMar 18, 1987 10:33 AM
Nothing at all to C, Larry… if you can read Pascal or Modula, you can read C with little additional trouble. Pick up a copy of Waite's C Primer Plus, and DO the examples. It has bugs, but is one of the better introductions I've found. And if you get into it bigtime, pick up K&R and the AT&T C Programmer's Handbook… indispensible. Rick
#59447From: John DraperMar 18, 1987 6:51 PM
Rick, I have the C Primer Plus, A Book on C, C Language For Programmers, C Programming Guide, The C Programmers Guide, along with Amiga specific ones, Inside the Amiga, Amiga Programmers Handbook, Inside Amiga Graphics, Programmer's Guide to the Amiga, The complete RKM/Intuition/Hardware etc. set, and numerous examples and tutorials on disk, in magazines, etc. I have successfully programmed in assembler, BASIC, COMAL, Modula 2, Pascal, Icon, Tutor, Fortran, LOGO, and probably a few that I've forgotten about. All this said, I now confess that there are three languages that I've tried that I jast can't "get the hang of". They are FORTH, LISP, and C. I do occasionally go back and try these again, with the same result each time, pure frustration. Regards, Larry.
#59445From: Richard Rae/SYSOPMar 18, 1987 6:41 PM
> Then why are you multiplying IntuitionBase by nothing? I'm not. Several symbols in C are context dependent, in the same way "=" can mean "is equal to" or assignment in BASIC. "*" is one of these. When used between two quantities (variable or constant), * indicates multiplication as you'd expect. When used in a unary fashion, before a single term, it indicates indirection… a pointer, to be exact. Thus value is a variable, whereas *value is a pointer to the value. The other thing you need to know is that a data type in parens is a "type cast", which explicitly says "change this type to that type". So, if you need to assign a float to an integer, you can say integer=(int)float. So, (struct IntuitionBase *)OpenLibrary(etc) says "cast the quantity which is OpenLibrary(), that is, the result of the call, to type pointer-to-structure-of -type-IntuitionBase". I know, clear as mud, right? It does take some getting used to. Rick
#59458From: John DraperMar 18, 1987 7:28 PM
>getting used to. It sure does. When I look at that, I do realize that it is a cast (I trust you noticed the toungue in cheek). However, to have it make any sense to me at all, it would need to be written differently (if that were allowed). As it is, it is one of the many parts of C that make so little sense to me that I have to memorize it, which is a far different thing than learning it. For instance, when I see that particular line, or one like it, I wonder why I can't: 1. say… (long)OpenLibrary(… 2. say… (*)OpenLibrary()… 3. Not bother casting the return value at all, since it should return a pointer anyway, and if my lvalue is a pointer already then there is no conflict. I mean really, why does a cast to type pointer need to specify that it is a pointer to a structure anyway? Regards, Larry.
#59380From: Charlie HeathMar 18, 1987 12:40 AM
You gotta make your *own* IntuitionBase like so: struct IntuitionBase *IntuitionBase; main() { IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library, 31L) /* ACK! OVERSHOT! */
#59388From: Richard Rae/SYSOPMar 18, 1987 2:48 AM
Yeah, thats what Steve and Don finally pounded through my thick skull… said pounding, however, only unveiling other, more obtuse bugs which were probably better left undiscovered. <Sigh> WHEN am I gonna get 3.40! Rick
#59320From: Roy S. LauferMar 17, 1987 6:42 PM
Hi Rae, Let me see if I can make the following make sense!: long *tloc,*clock; struct tm *timevalue,*localtime(); . clock = (long *)time(tloc); timevalue = (struct tm *)localtime(&clock); printf("This is the %dth month in the year.\n",timevalue->tm_mon); . etc. . I hope that this doesn't get reformatted into obscurity! If you're confused feel free to shout! -RSL-
#59326From: Richard Rae/SYSOPMar 17, 1987 7:10 PM
Roy, Yes! Don Curtis beat you to the punch, just slightly, with the cure. It seems localtime() DOES pick a struct at random (well, almost! 8), and returns the pointer to THAT… I, in turn, was not pointing to _its_ struct, instead thinking somehow that I was supposed to be telling it about my struct. Adding the pointer->member clause seems to have cured the problem. See how much trouble I could have saved myself, if you'd just posted the source to your clock too! 8) You might want to see my reply to Don's message for more info and further questions. BTW, your formatting came out just fine. Nybbles!
#59718From: Roy S. LauferMar 20, 1987 5:11 PM
I'm glad that you solved your problem. I'm not trying to hide any great programming secrets, it's just that the source would be embarassing to show without significant "cleaning up"! As always, I'm always available to post bits and pieces of source to show how I got RSLClock to due any of its functions. BTW, now that I have a copy of Aztec 3.4a I'm having a hell of a time compiling PopCLI2's WBC.a on it! Anyone know why my assembler coughs up when it finds a '*' in the source! -RSL-
#59735From: Richard Rae/SYSOPMar 20, 1987 7:41 PM
You've GOT 3.4??? Hooray! Maybe mine will show up before too much longer. It's getting to be a pain working around the limitations in the 3.2/1.2 combination. Can't help you with the assembler, as I haven't used Aztec's directly yet. Sorry.
#59378From: Charlie HeathMar 18, 1987 12:34 AM
#include <time.h> main() { struct tm *ptr; long value; value = time(); ptr = localtime(&value); /* I'm not sure of the *input* here */ printf("%d %d", ptr->tm_sec,ptr->tm_min); } /* Hope this heps … er …. helps */
#59387From: Richard Rae/SYSOPMar 18, 1987 2:47 AM
Cheath… Yeah, we got it going. I didn't realize there was a local structure, and was trying to get it to put the data in my struct. Once it was pointed out that it used it's own struct, everything fell in place. Well, not everything… been fighting a relatively obscure one with Don and Steve's help (actually, they did all the brainstorming, I just listened. 8). Thanks for the help! Rick
#59377From: Charlie HeathMar 18, 1987 12:31 AM
The localtime() function declares it's own static data structure which it passes you back a pointer to. I'll have a look at your next message and see if I can figure out what is wrong- …cheath