#Lost at C (Again!)
22 messages in this thread
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!
#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);
}
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
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
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
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
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.
Lessee…
That would be…
IntuitionBase = (struct IntuitionBase
*)OpenLibrary("intuition.library",LIBRARY_VERSION);
Nothing to it. 😉
Rick
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.
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
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.
> 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
>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.
You gotta make your *own* IntuitionBase like so:
struct IntuitionBase *IntuitionBase;
main()
{
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library, 31L)
/* ACK! OVERSHOT! */
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
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-
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!
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-
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.
#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 */
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
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