-1

I had finished reading about stdio.h functions and need some small clarifications.

Please take a minute to give short explanations for the following:

1) tmpnam() : It only gives us a string containing a unique file-name, but what to do about the file extensions?Will we have to use strcat() each time to add the file extension to the file name?

2) rand() : What does the following mean in the context of rand() (Taken from cplusplusreference)?:

"In C, the generation algorithm used by rand is guaranteed to only be advanced by calls to this function"

I checked it, repeatedly calling rand() one after another for the same seed, but it doesn't give increasing values!

3) getc() : What does the part in bold mean in the following description of the parameter of getc() taken from the same site(getc())?

"---Parameter

Pointer to a FILE object that identifies an input stream.

Because some libraries may implement this function as a macro, and this may evaluate the stream expression more than once, this should be an expression without side effects."

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Jugni
  • 255
  • 5
  • 12
  • From your title it really looks as if you are using the C library from C++? Don't look for C++ references for C library functions, take them directly from the C documentation. And please, really, don't ask 3 questions in one. Do a separate research for each of the questions and look in what you find here on SO. There are, e.g, a lot of questions and answers that deal with `rand` and how it works with seeds that are unchanged etc. – Jens Gustedt May 21 '13 at 20:34
  • For 3) please search for "side effect" and "macro evaluation", you should also find some information on that. – Jens Gustedt May 21 '13 at 20:36
  • @JensGustedt I won't do it again.I really felt each bit was too small for a separate question.But please,help me out this time for this question with nutshell explanation of each one. – Jugni May 21 '13 at 20:36
  • @JensGustedt Yes,you gave a good clue for the 3). – Jugni May 21 '13 at 20:37
  • This really should have been three separate questions. And incidentally, `rand()` is declared in ``, not in ``. – Keith Thompson May 21 '13 at 20:45
  • @KeithThompson OMG,I've claimed `rand()` as a `stdio.h` function!!Didn't occur to me at all,that embarrassing mistake. **CRINGEEEEEEE** – Jugni May 21 '13 at 21:17
  • @KeithThompson Is there any other way to add filename extension to the name obtained through `tmpnam()` other than using `strcat()`?It gets more messy if we have passed `NULL` to `tmpnam()`,doesn't it?In the latter case,can we use `strcat()` on the static internal array that stores the name? – Jugni May 21 '13 at 21:20
  • 1
    You *cannot* safely use `strcat` to extend the string pointed to by the return value of `tmpnam(NULL)`. If you call `tmpnam` with a non-NULL argument, then you supplied the buffer yourself, and it's up to you to determine whether you can safely write to it. Why do you need to add an extension? On many systems, extensions are just part of the file name. – Keith Thompson May 21 '13 at 21:28
  • @KeithThompson What I mean to ask is,`tmpnam(buffer)` gets us unique name in the buffer.But it's upto us what for we use that name,whether for a `.txt` file,for an `.exe` file or for a `.pdf` file.If I want to copy an **exe** file and I want the new file to have a unique name,and suppose I get that name using `tmpnam()`,then would I have to add `.exe` to that name on my own using `strcat()`?Isn't there a better way to do this?I hope you got my point. – Jugni May 21 '13 at 21:49
  • 1
    @Jugni: As the Linux [man page](http://linux.die.net/man/3/tmpnam) for `tmpnam` says, "Never use this function". It's not for generating *unique* names, it's for generating names for *temporary* files, typically files that won't outlive the execution of your program. And there are better ways to do even that. – Keith Thompson May 21 '13 at 22:02
  • @KeithThompson Thanks for clarifying that `tmpnam()` is tied to generating unique names for temporary files created with `tmpfile()`.Now I can see the whole thing.That would serve my present purpose.Thanks a lot.Your comments were equivalent to a good answer!! – Jugni May 21 '13 at 22:09

1 Answers1

1
  1. You can't modify the filename returned unless you supplied a buffer yourself and know how big it is. Any string copying or modifying function will work.
  2. It means that the sequence of numbers returned by rand() is affected only by calls to the rand() function itself: no matter what you do in between calls to rand(), you'll get the same outputs. That is, the underlying function is only advanced by calls to rand(). That doesn't mean that the output is always increasing.
  3. It means that getc() may be a macro that evaluates its argument twice. Why don't you try and work out what possible outcomes this code might have:

    int i = 0;
    (void)getc((++i,stdin));
    printf("%d\n", i);
    

    Here's an example of an implementation that specifically uses a macro for getc(): AIX docs. If I remember correctly, you'll get into trouble too on AIX if you don't pass exactly the right pointer to fileno and dirfd, and probably others too. It looks like OpenSolaris does this too with this definition, though I don't have a copy to hand (glibc, FreeBSD, don't use a macro).

    #define getc(p)     (--(p)->_cnt>=0? ((int)*(p)->_ptr++):_filbuf(p))
    
Nicholas Wilson
  • 9,435
  • 1
  • 41
  • 80
  • How are you giving an output stream to `getc()`?I ran it,it prints **1**.But how come you gave `stdout` in place of `stdin`? – Jugni May 21 '13 at 20:23
  • And what purpose does casting the return to `void` serve? – Jugni May 21 '13 at 20:25
  • @Jugni OK, fine, you can use stdin if you prefer. The point is, the code could happily print 2, 3 or more. The cast is just a way of saying, "we don't care about the result, that's not the point of this line of code". – Nicholas Wilson May 21 '13 at 20:26
  • What you mean `you can use stdin if you prefer`?`If stdout doesn't work,use stdin`,is it?This is programming,you can't be that casual.And it doesn't and won't print 1,2,3, it accepts a character from the console and prints a 1.That's all it is supposed to do,that's all it does. – Jugni May 21 '13 at 20:27
  • I mean, whether it's stdin or stdout or any other stream is irrelevant in this example. It can print 2, that's the entire point of the example, and it's the pitfall that I'm trying to explain to you. That's what it means when it says, "this should be an expression without side effects" in the text you quoted. – Nicholas Wilson May 21 '13 at 20:30
  • Actually what I meant Nicholas is that you can't be so casual as to say `getc()` can have `stdout` as argument.It is clearly stated about that argument for `getc()` that it should be `Pointer to a FILE object that identifies an input stream.` – Jugni May 21 '13 at 20:38
  • (1) `getc()` takes one argument; your sample would be appropriate for `putc()`. (2) If you go by the standard, the definition of `getc()` says: _The getc function is equivalent to fgetc, except that if it is implemented as a macro, it may evaluate stream more than once, so the argument should never be an expression with side effects._ So in theory, `putc(i++, fp)` incrementing the character `i` should be OK; the standard does not allow the macro to evaluate it more than once. What you couldn't do, though, is `getc(fp[i++])` where you have `FILE *fp[10];` say. Similarly for `putc()`. – Jonathan Leffler May 22 '13 at 00:00
  • 1
    @Jonathan Thanks for the extra info, but I think my use of the comma operator was correct. Certainly the three lines given compile, and print "1" on glibc, "2" on Solaris, demonstrating clearly the problem caused by multiple evaluations. If the comma-operator example with getc is problematic, I'd be happy to know why. – Nicholas Wilson May 22 '13 at 09:41
  • Oops — embarrassed ... I failed to notice the double parens making it a comma operator. I'll proffer to you that anyone who writes a comma expression like that should be shot routinely until they repent of their evil ways, but it would be 'OK'. A more plausible expression with side-effects is an array of file streams (think `tee` program), but that doesn't alter that your exposition was OK and my deconstruction inaccurate (even if it has some helpful extra information). – Jonathan Leffler May 22 '13 at 14:05