[comp.lang.c] strncpy

gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/18/88)

In article <1666@solo10.cs.vu.nl> maart@cs.vu.nl (Litmaath Maarten) writes:
>If you want to copy part of a string into a buffer, do you complain you can't
>give a count to strcpy()? Or do you say: hey, strcpy() doesn't do what I want,
>let's use another function (which happens to be strncpy())?

Except strncpy() has its own problems when the limit is reached,
just as someone observed that fgets() does!

The important idea is that one must think HARD about the implications
of the specifications for library functions, in order to use them
safely in robust, secure code.  There is no easy road to rightness.

poser@csli.Stanford.EDU (Bill Poser) (12/21/89)

	Why is it that strncpy(3) does not null terminate
the string if the length of the source string is greater than
or equal to the length of the target buffer? I cannot think of
any circumstances in which this behaviour is desirable, and
always end up null terminating it myself. The only case in
which a non-null-terminated string might be useful would be
one in which a different representation for strings (e.g.
descriptors) is used, in which case the use of str(n)cpy would
not be appropriate anyhow. It seems to me that the behaviour
of strncpy provides: (a) a source of bugs for people who don't
bother to arrange null-termination themselves; (b) extra work for
those who take care; or, (c) just enough of a pain to be unsafe and
use strcpy(3).

	So I claim that strncpy is mis-designed and should
null-terminate. Any comments?

						Bill

cns@stiatl.UUCP (Chris Straut) (12/21/89)

In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill Poser) writes:
>	Why is it that strncpy(3) does not null terminate
>the string if the length of the source string is greater than
>or equal to the length of the target buffer? 
                 [ other stuff deleted ]


I agree that strncpy should null terminate the resulting string.  The 
definition of a string in the C language is a null terminated char array.
And the function called (str)ncpy indicates a string operation, which by
default should create a null terminated string.  To overcome this 'feature'
we wrote our own strncpy function, which is benefical to the unsuspecting
programmer (or novice), and the result is a null terminated string.
-- 
Christopher Straut             | Go Jackets!!!!!         gatech!stiatl!cns
Sales Technologies, Inc        |
3399 Peachtree Rd, NE          |
Atlanta, GA  (404) 841-4000    |

bengsig@oracle.nl (Bjorn Engsig) (12/21/89)

Article <11509@csli.Stanford.EDU> by poser@csli.Stanford.EDU (Bill Poser) says:
|
|	Why is it that strncpy(3) does not null terminate  ...
strncpy always copies exactly n characters to the destination string by null-
padding or truncating.  A similar behaviour is also found in a declaration like

  char thing[][3] = { "a", "ab", "abc", "de" };

where each element of thing is an array of 3 characters (i.e. thing[2] is
not null terminated, and puts(thing[2]) would print abcde).

A way to do a limited string copy is

  dst[0] = 0;
  strncat(dst,src,n);

since strncat always null-terminates.
-- 
Bjorn Engsig,	Domain:		bengsig@oracle.nl, bengsig@oracle.com
		Path:		uunet!{mcsun!orcenl,oracle}!bengsig

tcm@srhqla.SR.COM (Tim Meighan) (12/22/89)

In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU
 (Bill Poser) writes:

> So I claim that strncpy is mis-designed and should null-terminate.
> Any comments?

Well, I generally make sure the array I'm copying INTO is larger than
what I'm copying.  That way the null terminator gets copied in as well
and everything is cool.

I could make the argument that it's poor programming practice to be
copying strings into arrays that aren't large enough to hold them, and
that strncpy() is merely making the best of a bad situation.  You could
probably counter with an excellent example of a real-life instance where
the situation arises.  I would then counter that if you're doing things 
that are that sophisticated, it's a good time to write your own function
that works just like strncpy(), but that does string termination the
way you want it to be done!

Personally, I think strncpy() works just fine as is.  As I said, I
have never had a situation where I needed it to do anything other
than what it does.

Tim Meighan
SilentRadio

"The text strings were shifted in memory with care . . .
     with the hope that NULL TERMINATOR soon would be there!"

sullivan@aqdata.uucp (Michael T. Sullivan) (12/22/89)

From article <11509@csli.Stanford.EDU>, by poser@csli.Stanford.EDU (Bill Poser):
> 
> 	Why is it that strncpy(3) does not null terminate
> the string if the length of the source string is greater than
> or equal to the length of the target buffer? I cannot think of

It's so you can do things like:

	strncpy(s1, s2, len)[len] = '\0';

and really freak people out! :-)
-- 
Michael Sullivan          uunet!jarthur.uucp!aqdata!sullivan
aQdata, Inc.
San Dimas, CA

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (12/22/89)

In article <8313@stiatl.UUCP> cns@stiatl.UUCP (Chris Straut) writes:
| In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill Poser) writes:
| >	Why is it that strncpy(3) does not null terminate
| >the string if the length of the source string is greater than
| >or equal to the length of the target buffer? 
|                  [ other stuff deleted ]
| 
|	[  answer deleted  ]

  I was asked this question just a few days ago mydelf. After some
thinking, this appears to be consistent with other behavior, namely
fgets() which drops the trailing newline if the buffer is too small.

  This makes sense if you think of strncpy() as a way to copy to a
buffer without overflow. For buffer size N you copy N-1 characters and
manually force an end of string in the last byte. If you think of it as
a way to copy N characters from a string to a buffer which is always big
enough it doesn't make sense. It's a question of intended use.

  We hacked out a quick version which does always terminate the string
rather than add logic to all the places in which it was being used.
-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
"The world is filled with fools. They blindly follow their so-called
'reason' in the face of the church and common sense. Any fool can see
that the world is flat!" - anon

maart@cs.vu.nl (Maarten Litmaath) (12/22/89)

In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill Poser) writes:
\
\	Why is it that strncpy(3) does not null terminate
\the string if the length of the source string is greater than
\or equal to the length of the target buffer? I cannot think of
\any circumstances in which this behaviour is desirable, and
\always end up null terminating it myself. [...]

So you have to write nstrncpy(), a function that always null-terminates the
destination, just like you have to write your own str*c{at,py} functions if
you want them to return something USEFUL, instead of their first arguments,
e.g. the new length of the destination. :-(
-- 
1755 EST, Dec 14, 1992: Henry Spencer is put on a one-way mission to the moon.|
  Maarten Litmaath @ VU Amsterdam:  maart@cs.vu.nl,  uunet!mcsun!botter!maart

poser@csli.Stanford.EDU (Bill Poser) (12/22/89)

I should clarify that: (a) I know perfectly well HOW strncpy works. My
question concerned the rationale for this design; (b) I know that it is
not hard to produce null-termination and indeed have my own version of
strncpy that does this. But the fact that it isn't hard to produce
null termination doesn't explain why the standard version was designed
the way it was. There is nothing terribly difficult about anything in the
string library.

So far I have heard of one good use for strncpy without null termination.

I have also been told that it is useful for copying into fixed length
char arrays which are not intended to be null-terminated when full.
I am aware of such string representations, but those aren't the standard
C string representation and so the question arises as to why the
standard string library should include a function that doesn't fit the
usual representation of strings.

rli@buster.irby.com (Buster Irby) (12/22/89)

cns@stiatl.UUCP (Chris Straut) writes:

>I agree that strncpy should null terminate the resulting string.  The 
>definition of a string in the C language is a null terminated char array.
>And the function called (str)ncpy indicates a string operation, which by
>default should create a null terminated string.  To overcome this 'feature'
>we wrote our own strncpy function, which is benefical to the unsuspecting
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
>programmer (or novice), and the result is a null terminated string.

CAUTION: There is a lot of existing software in the world that
would break if the operation of strncpy or any other standard
library function were suddenly changed.  You are asking for
trouble any time you change the operation of a standard library
function such as strncpy, and I would strongly suggest that you
not do it.  First of all, what happens when you take a piece of
software that was not developed inhouse and compile it using your
new strncpy function?  Or what happens when you hire a senior
level C programmer who is used to the way strncpy is documented
to work?  You are asking for trouble, and believe me, it can cost
a lot of time and money to track down bugs which you introduce
into the code like this.  If you must create your own specialized
version of any standard library function, you should call it by
your own specialized name, not by its standard name.
-- 
Buster Irby  buster!rli

meissner@skeptic.osf.org (Michael Meissner) (12/22/89)

In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill
Poser) writes:

|	Why is it that strncpy(3) does not null terminate
|the string if the length of the source string is greater than
|or equal to the length of the target buffer?

Strncpy was created to deal with the pre-Berkeley UNIX file system,
whose directory entry took up exactly 16 bytes:

	 2 bytes for the inode # of the file
	14 bytes for the filename

If the filename was exactly 14 characters, no null would be used (>14
characters would be truncated).  This fact blew away some early
attempts at building a readdir function, which is spec'ed to return a
null terminated name.

I believe, that the kernel would compare all 14 bytes to see if they
were equal when doing the namei (name to inode) transformation, which
is why strncpy is required to zero out all bytes, if the string is
less than n bytes.

In addition to limiting names to the wierd 14 character limit, I think
that the above scheme also is responsible for breaking large disks
into tiny pieces, since each disk piece could not have more than 65K
inodes.  I suspect that many UNIX systems will shortly be in for the
same shock, since 1GB disks are now appearring, and we should soon hit
the limit for 32-bit inode numbers.  Even if the system can support a
multiple GB disk, single files will probably still be limited to 2GB,
unless your system supports 64-bit longs (or uses the long long kludge
+ prototypes all the time).

|					       I cannot think of
|any circumstances in which this behaviour is desirable, and
|always end up null terminating it myself. The only case in
|which a non-null-terminated string might be useful would be
|one in which a different representation for strings (e.g.
|descriptors) is used, in which case the use of str(n)cpy would
|not be appropriate anyhow. It seems to me that the behaviour
|of strncpy provides: (a) a source of bugs for people who don't
|bother to arrange null-termination themselves; (b) extra work for
|those who take care; or, (c) just enough of a pain to be unsafe and
|use strcpy(3).
|
|	So I claim that strncpy is mis-designed and should
|null-terminate. Any comments?
|
|						Bill

djones@megatest.UUCP (Dave Jones) (12/22/89)

From article <11509@csli.Stanford.EDU>, by poser@csli.Stanford.EDU (Bill Poser):
> 
> ... I claim that strncpy is mis-designed and should
> null-terminate. Any comments?
> 


I grepped through a bunch of my code, and it all adds a null everywhere
it calls strncpy. So a null-terminating strncpy would seem to be useful.
But don't name it strncpy! There just may be code out there that depends on
it working the way it's documented. Call it strncpy0 or something.

jonathan.forbes@canremote.uucp (JONATHAN FORBES) (12/22/89)

If the source string is larger than the destination string, and you use 
strncpy(), then you will be overwriting memory in the destination 
string!  (assuming they both have the same amount of space allocated.)
---
 * Via ProDoor 3.1R 

exspes@gdr.bath.ac.uk (P E Smee) (12/22/89)

In article <11510@csli.Stanford.EDU> poser@csli.stanford.edu (Bill Poser) writes:
>
>I should clarify that: (a) I know perfectly well HOW strncpy works. My
>question concerned the rationale for this design; 

I suspect it has to do with the original design of the unix directory
structure.  Filenames were limited to 12 (14? been so long since I
used one, I'm not sure of the number) characters, and the directory
structure had a char[exactly-that-size] variable to HOLD the filename.
So, when putting a filename into or out of a directory structure, you
wanted it to be null-terminated if and only if it was shorter than that
variable.  A maximum-length filename could NOT be null terminated in
the describing structure.

As to why they decided to do that, sheer byte-saving, I suppose (1 per
file in your directory hierarchy).  Maybe it made directory entries fit
more nicely into whatever their disk blocksize was.
-- 
Paul Smee, Univ of Bristol Comp Centre, Bristol BS8 1TW, Tel +44 272 303132
 Smee@bristol.ac.uk  :-)  (..!uunet!ukc!gdr.bath.ac.uk!exspes if you MUST)

poser@csli.Stanford.EDU (Bill Poser) (12/22/89)

In article <621@buster.irby.com> rli@buster.irby.com (Buster Irby) writes:
>
>CAUTION: There is a lot of existing software in the world that
>would break if the operation of strncpy or any other standard
>library function were suddenly changed.

I at least was not calling for a redefinition of strncpy in my
posting, only asking whether there was a good reason for it to behave
as it does. My own null-terminating version is called tstrncpy, and
I would guess that other people's have distinct names too. 

fredb@llama.rtech.UUCP (Fred Buechler) (12/22/89)

From article <11509@csli.Stanford.EDU>, by poser@csli.Stanford.EDU (Bill Poser):
> 
> ... I claim that strncpy is mis-designed and should
> null-terminate. Any comments?
> 
>
I have found strncpy to be useful when working in mixed language environments
where the other languages don't use null terminated strings, particularly to
write shared data structures.

Fred.

cns@stiatl.UUCP (Chris Straut) (12/22/89)

In article <621@buster.irby.com> rli@buster.irby.com (Buster Irby) writes:
>cns@stiatl.UUCP (Chris Straut) writes:
>
>>I agree that strncpy should null terminate the resulting string.  The 
>>definition of a string in the C language is a null terminated char array.
>>And the function called (str)ncpy indicates a string operation, which by
>>default should create a null terminated string.  To overcome this 'feature'
>>we wrote our own strncpy function, which is benefical to the unsuspecting
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
>>programmer (or novice), and the result is a null terminated string.
>
>CAUTION: There is a lot of existing software in the world that
>would break if the operation of strncpy or any other standard
>library function were suddenly changed. 
                  [ alot of other stuff deleted ]


We didn't call the new function strncpy.  Sorry if the text above was
misleading.  We have written a set of library functions to enhance the
C run-time library as well as increase its functionality.  We currently
do development on three different platforms, therefore the need for portable
library functions which can be maintained in-house.

We currently employ alot of CO-OP programmers, and many are not very
experienced in the C language.  The use of our libraries assist these CO-OPs
in overcoming these holes in the C run-time library naming convention.
We are currently putting together a developers guide for in-house use,
which will document the characteristics of the C libarary as well as
our own C functions which bring to the attention certain "features" of
the language run-time library.

-- 
Christopher Straut             | Go Jackets!!!!!         gatech!stiatl!cns
Sales Technologies, Inc        |
3399 Peachtree Rd, NE          |
Atlanta, GA  (404) 841-4000    |

sullivan@aqdata.uucp (Michael T. Sullivan) (12/23/89)

From article <11510@csli.Stanford.EDU>, by poser@csli.Stanford.EDU (Bill Poser):
> 
> I have also been told that it is useful for copying into fixed length
> char arrays which are not intended to be null-terminated when full.
> I am aware of such string representations, but those aren't the standard
> C string representation and so the question arises as to why the
> standard string library should include a function that doesn't fit the
> usual representation of strings.

Isn't it nice that there IS a function that handles the non-standard case.
I think your question really should be why doesn't the standard library
include a function that does a null terminated strncpy.
-- 
Michael Sullivan          uunet!jarthur.uucp!aqdata!sullivan
aQdata, Inc.
San Dimas, CA

jss@jra.ardent.com (12/23/89)

In article <11515@csli.Stanford.EDU> poser@csli.stanford.edu (Bill Poser) writes:
>
>I at least was not calling for a redefinition of strncpy in my
>posting, only asking whether there was a good reason for it to behave
>as it does. 

Not to pick on Bill, because I see questions like this all the
time in this newsgroup.  But this is not a well posed (groan moan, 
I couldn't resist :-) question because we don't know what kind of reason 
will be "good".  Do you want 

	Origin:		There was a glitch in the XYZ-1 architecture 
			that meant the routine was 10 times faster
			than the obvious alternative.

	Historical: 	When the code was moved from the XYZ-1 to the
			FOOBAR-990000000 this behavior was unmodified.
			On the DWIM-9 it was fixed, but when X3J11 decided 
			to standardize there weren't any DWIM-9's around
			and there were zillions of lines of code derived
			that dependend on the bug so they standardized 
			on the XYZ-1 behavior.

	Rationale:	It ought to work that way because ... 

Usually the dominant reason is historical, and frequently there
are no good rationales.  But is the historical explanation a
"good" one? 

Please, if you ask a question about why some library function
behaves the way it does, explain what motivates the question
(idle curiosity is fine with me) and what category of answer 
you're interested in. 

Jerry Schwarz

mike@relgyro.stanford.edu (Mike Macgirvin) (12/23/89)

In article <1947@crdos1.crd.ge.COM> davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) writes:
>In article <8313@stiatl.UUCP> cns@stiatl.UUCP (Chris Straut) writes:
>| In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill Poser) writes:
>| >	Why is it that strncpy(3) does not null terminate
>| >the string if the length of the source string is greater than
>| >or equal to the length of the target buffer? 
>  I was asked this question just a few days ago mydelf. After some
>thinking, this appears to be consistent with other behavior, namely
>fgets() which drops the trailing newline if the buffer is too small.
 ^^^^^^^
>  We hacked out a quick version which does always terminate the string
>rather than add logic to all the places in which it was being used.
	Since it was mentioned, has anyone but me ever wondered WHY fgets()
should return the newline at all? 'gets()' doesn't. I finally got tired of
stripping off newlines, and created 'fgetsn()', which I prefer for reading
in text lines from a file....

#include <stdio.h>
  
  /* Function which behaves identically to fgets(),
     except that the trailing newline is not included
     in the string. It always pissed me off that fgets()
     and gets() differ in this behaviour, complicating
     the life of any programmer who may wish to take input
     from either a file or stdin, and treat them the same.
     It also makes a mess of strcmp()'s from a file.
     If you feel the same way, write your congressman or
     ANSI, or add this function to libc.
   */

char * fgetsn(string,count,stream)
     char * string;
     int count;
     register FILE * stream;
{
  int ch;
  register char * pointer = string;
  if(count <= 0)
    return(NULL);
  while (( -- count) && ((ch = getc(stream)) != '\n')) {
    if(ch == EOF) {
      if(pointer == string)
	return(NULL);
      break;
    }
    * pointer ++ = ch;
  }
  * pointer = '\0';
  return(string);
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  Mike Macgirvin              Relativity Gyroscope Experiment (GP-B)    +
+  mike@relgyro.stanford.edu   (36.64.0.50)                              +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

poser@csli.Stanford.EDU (Bill Poser) (12/23/89)

Jerry Schwartz suggests that my question about why strncpy does not
null terminate was ill-formulated because I didn't say what sort of
answer I was looking for. I disagree. Sometimes only one kind of answer
is appropriate. For example, if you're designing a language the only
kind of answer you are interested in is rationale, so you can decide if
the comparable construct in your own language should work that way.
But if you want to know why a feature of a language is the way it is,
then the nature of the explanation is open. It may be that there is
an explicit rationale or it may be that there is no particular rationale
for doing it that way and that the reason is purely historical. But
you don't know in advance.

bill@twwells.com (T. William Wells) (12/24/89)

In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill Poser) writes:
:       So I claim that strncpy is mis-designed and should
: null-terminate. Any comments?

Who cares? I claim that having an appendix makes a human
mis-designed and that we should not have one. That won't change a
thing.

Strncpy is what it is. If you want a new function, create it.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

poser@csli.Stanford.EDU (Bill Poser) (12/24/89)

In response to my query about why strncpy does not null terminate
Dr. T. Andrews <cdis-1!tanner@uunet.UU.NET> writes:

>Your brain is probably broken.  The reason that strncpy() does
>not null terminate is so that the supplied buffer is not over-run.
>If it were to do as you suggest, then it would be of no value as the
>data following the destination might be randomly clobbered.
>Alternatively, truncating the source one byte too soon would be
>unhelpful: you would lose data for which you had space.

(Since direct mail seems to be problematic, I respond here.)
One can't help but be overwhelmed by this charming, witty, and insightful
response. Only a genius like Dr. Tanner would think of not overflowing
the buffer. The "waste" of the terminating null is REQUIRED so long
as one conforms to the usual, null-terminated representation of strings
in C. All other representations of arbitrary length strings require
similar overhead, e.g. a character count in the descriptor. The
case in which the terminating null or character count can be dispensed
with is that of strings with a known maximum length, as in pre-Berkeley
style directory entries, for which I have been told strncpy was designed.
In sum, as part of the standard C string implementation, strncpy is
deviant. It was actually designed to deal with a different representation
of strings, and doesn't quite form a coherent part of the standard string
library.

john@chinet.chi.il.us (John Mundt) (12/24/89)

In article <8313@stiatl.UUCP> cns@stiatl.UUCP (Chris Straut) writes:
>In article <11509@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill Poser) writes:
>>	Why is it that strncpy(3) does not null terminate
>>the string if the length of the source string is greater than
>>or equal to the length of the target buffer? 
>                 [ other stuff deleted ]
>
>
>I agree that strncpy should null terminate the resulting string.  The 
>definition of a string in the C language is a null terminated char array.
>And the function called (str)ncpy indicates a string operation, which by
>default should create a null terminated string.  To overcome this 'feature'
>we wrote our own strncpy function, which is benefical to the unsuspecting
>programmer (or novice), and the result is a null terminated string.

C has allowed you to shoot yourself in the foot if you want to.  And the
man page clearly says that the string is not null terminated if it runs
to the full length permitted by the integer argument.

Good reasons abound.  For example, if you wish to replace a *part* of
a string with something else, strncpy allows you to do that.  Having
an terminating \0 stuck in there would truncate the string and wipe
out a character.  You'd have to do some fancy footwork to get the
tail end of the string stuck on the end in such a situation.  

Not to mention that with the length known, it is easy as pie
to null terminate the string if necessary:

#defind LENGTH 10

some_func(s1)
char *s1;
{
char buf[500];
	buf[LENGTH] = '\0';
	(void)strncpy(buf, s1, LENGTH);
}
-- 
---------------------
John Mundt   Teachers' Aide, Inc.  P.O. Box 1666  Highland Park, IL
john@admctr.chi.il.us *OR* fred@teacha.chi.il.us
(312) 998-5007 (Day voice) || -432-8860 (Answer Mach) && -432-5386 Modem  

brucet@cpsc.ucalgary.ca (Bruce Thompson) (12/24/89)

I must be naive, and may be repeating things others have put in, but it seems
to me that if null termination is not needed/wanted, why not use bcopy?

==============================================================================
Bruce Thompson			| "I've got this terrible pain in all the
NovAtel Communications Ltd.	| diodes down my left side" - Marvin the
				| Paranoid Android
The opinions expressed are my own, and do not neccesarily reflect those of
NovAtel Communications Ltd. nor those of The University of Calgary.

thorinn@skinfaxe.diku.dk (Lars Henrik Mathiesen) (12/27/89)

brucet@cpsc.ucalgary.ca (Bruce Thompson) writes:

>I must be naive, and may be repeating things others have put in, but it seems
>to me that if null termination is not needed/wanted, why not use bcopy?

strncpy() seems to be intended for a fixed-length, null-padded string
representation. bcopy() can, indeed, be used to copy such a string to
another (of the same length), but strncpy is necessary to convert
null-terminated strings to null-padded strings.

In applications where the null-padded strings are full-word aligned,
they have the further advantage that they can be moved and compared
(for equality) with full-word operations. (On big-endian machines with
unsigned char's, even ordered comparisons can be done that way.)

Here's how you convert between the formats:

	#define LENGTH 14		/* Today's magical number */
	char padded[LENGTH];
	char terminated[LENGTH + 1];

	/* Move terminated to padded */
	strncpy(padded, terminated, LENGTH);

	/* Move padded to terminated */
	strncpy(terminated, padded, LENGTH);
	terminated[LENGTH] = '\0';

Actually the last move could just as well use bcopy(). If you need to
guarantee that the move only modifies the destination up to the
terminating null, no single library routine seems to fill the ticket.
A buffer with a permanent extra null, maybe:

	/* Move padded to terminated, no extra nulls */
	static __move_buffer[LENGTH + 1];

	bcopy(padded, __move_buffer, LENGTH);
	strcpy(terminated, __move_buffer);

Given the general lack of support for null-padded strings in the
standard library, you will either have to do something like that
before accessing one at all (even getting its length), or you will
have to write a set of support routines yourself.

Come to think of it, strnlen() would be really useful sometimes --- or
even, safe_strlen(const char *str, size_t max): Returns the length of
the string pointed to by _str_ if _str_ points to valid memory and the
string is not longer than _max_, otherwise it returns -1. But this is
more a question of safe programming than of string representation.

--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark      [uunet!]mcvax!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers.      thorinn@diku.dk

tanner@ki4pv.UUCP (Dr. T. Andrews) (12/27/89)

In <11527@csli.Stanford.EDU>, From: poser@csli.Stanford.EDU (Bill Poser) writes...
) Only a genius like Dr. Tanner would think of not overflowing
) the buffer.
At the very least, we may assume that people at Stanford have not
considered allocating a buffer of sufficent size for their purposes.

) The "waste" of the terminating null is REQUIRED so long as one
) conforms to the usual, null-terminated representation of strings
) in C.
If one had strings which fit neatly into that mold, one would surely
use strcpy(), not strncpy().  Except, of course, at Stanford, where
strncpy() and on buffers of known size are an important subject of
research; we expect Mr. Poser's paper on the same shortly.

) All other representations of arbitrary length strings require
) similar overhead, e.g. a character count in the descriptor.
I beg to differ.  By defining storage fields of a certain size, and
using strncpy() to manipulate them, "strings" of that size may be
handled without character counts in the descriptors.

That a function strncpy() has been provided for such a cases is nice,
but simply a convenience.

That they don't teach people about character arrays of known size
at Stanford is purely a local teaching decision and therefore not
a suitable subject for outside debate.

Of course, it may not be all of Stanford.  It may just be that Mr.
Poser's brain is broken.
...!{bikini.cis.ufl.edu allegra attctc bpa uunet!cdin-1}!ki4pv!tanner

tanner@cdis-1.UUCP (Dr. T. Andrews) (01/02/90)

In <11527@csli.Stanford.EDU>, poser@csli.Stanford.EDU (Bill Poser) writes...
) In response to my query about why strncpy does not null terminate ...
Your consideration of strcpy()/strncpy() is more than a little
reminiscent of a man who has in hand a claw hammer and a ball peen
hammer, and who wishes to know why he can't pull nails with the
latter.
-- 
{attctc gatech!uflorida}!ki4pv!cdis-1!tanner {bpa uunet}!cdin-1!cdis-1!tanner

konath@sj.ate.slb.com (Kannan Konath) (01/03/90)

I had asked this question,  around two weeks ago.  I received a good
number of answers by email.  Thanks for the replies. I had also
promised to post a summary.

Well here goes....

The question was:

Why does the C compiler not come up with an error when a function, say
foo,  of zero arguments gets called in the following manner.

	foo;  /* the parentheses are missing */

Answer:
I did not know it at that time, but the above statement "foo;" just
generates the address of the function foo.  Since expressions are
allowed to stand all by themselves in C, this passes and rightly so.
In fact this statement in particular has a null effect,  though in my
opinion expressions without any side effect should generate warnings
but then I suppose C's philosophy lies behind this lack of warnings
even in cases like this.

To detect these sort of errors, lint can be used.  In particular if
you are working on a BSD Unix system you need to use the "-h" flag
which points this error out.

john@wsl.UUCP (John Allen on wsl) (01/05/90)

strncpy() copies the termination NULL byte unless it would overrun the 
specified buffer. THIS IS COOL BEHAVIOUR. Why the hell else have a MAX
byte count specification.

-- 
People that don't know want to know from the people that do know and if the 
poeple that do know don't tell the people that don't know then the people
that don't know still won't know.
				   "Don't quote me on any issue whatsoever."

poser@csli.Stanford.EDU (Bill Poser) (01/06/90)

In article <000003Q@cdis-1.UUCP> tanner@cdis-1.UUCP (Dr. T. Andrews) writes:
>Your consideration of strcpy()/strncpy() is more than a little
>reminiscent of a man who has in hand a claw hammer and a ball peen
>hammer, and who wishes to know why he can't pull nails with the
>latter.

Not really. It's more like the question of why the carpentry shop
has a ball peen hammer (used for metal working) and doesn't have
a claw hammer. strncpy is a function evidently designed for use with
fixed-length character buffers, not the null-terminated strings that
are semi-standard in C. That makes one wonder why strncpy is included
with functions that are intended for use with null-terminated strings,
and why there is no "safe" copying function for the latter.

poser@csli.Stanford.EDU (Bill Poser) (01/06/90)

In response to my claim that:

	All other representations of arbitrary length strings
	require similar overhead, e.g. a character count in the
	descriptor.

in article <0000006@ki4pv.UUCP> tanner@ki4pv.UUCP (Dr. T. Andrews) writes:

>I beg to differ.  By defining storage fields of a certain size, and
>using strncpy() to manipulate them, "strings" of that size may be
>handled without character counts in the descriptors.

This is irrelevant. Fixed size strings are not arbitrary length strings
Please read messages before responding to them.

He continues:

>That they don't teach people about character arrays of known size
>at Stanford is purely a local teaching decision and therefore not
>a suitable subject for outside debate.

There is of course no basis for the inference that I do not know
about fixed size strings. Dr. Andrews seems to know this, as he
writes: 

	at Stanford, where strncpy() and on [sic] buffers of
	known size are an important subject of research; we expect
	Mr. Poser's paper on the same shortly.

In any case, I have no idea what is taught
on this subject at Stanford, as I am neither a student nor a member of the
Computer Science faculty. I first began to use C at Bell Labs.

kuro@vodka.Sun.Com (Teruhiko Kurosaka - Sun Intercon) (01/06/90)

In article <11616@csli.Stanford.EDU> poser@csli.Stanford.EDU (Bill Poser) writes:
 |are semi-standard in C. That makes one wonder why strncpy is included
 |with functions that are intended for use with null-terminated strings,
 |and why there is no "safe" copying function for the latter.
I have no opinion about philosophical correctness of the current behavior of
strncpy() but always do:
	strncpy(to, from, n);
	to[n]=0; 
This ensures the copied string is always null-terminated, if this is what you 
mean by "safe".
--
-------
T. Kurosaka ("Kuro") --- Sun Microsystems, Intercontinental Operation
Internet:kuro@Corp.Sun.Com Voice:+1(415)496-6121/336-5921 Fax:+1(415)858-0284
Mail: Mail Stop A6-18, 1870 Embarcadero Rd., Palo Alto, CA 94303, USA

bill@twwells.com (T. William Wells) (01/07/90)

In article <KURO.90Jan6014431@vodka.Sun.Com> kuro@Corp.Sun.Com writes:
: I have no opinion about philosophical correctness of the current behavior of
: strncpy() but always do:
:       strncpy(to, from, n);
:       to[n]=0;
: This ensures the copied string is always null-terminated, if this is what you
: mean by "safe".

Maybe you meant "to[n - 1]=0;"?

If the size of to is n, to[n] = 0 is illegal.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

kyriazis@ptolemy0.rdrc.rpi.edu (George Kyriazis) (01/08/90)

In article <1990Jan7.145719.15574@twwells.com> bill@twwells.com (T. William Wells) writes:
>In article <KURO.90Jan6014431@vodka.Sun.Com> kuro@Corp.Sun.Com writes:
>: I have no opinion about philosophical correctness of the current behavior of
>: strncpy() but always do:
>:       strncpy(to, from, n);
>:       to[n]=0;
>
>Maybe you meant "to[n - 1]=0;"?
>
>If the size of to is n, to[n] = 0 is illegal.
>

I think he means to[n] = 0.  strncpy() moves at most n bytes (0 to n-1), 
therefore byte n is not copied.  If you want to keep a string of length
n you better have a char array of n+1 characters..


  George Kyriazis
  kyriazis@turing.cs.rpi.edu
  kyriazis@rdrc.rpi.edu
------------------------------

msb@sq.sq.com (Mark Brader) (01/08/90)

> strncpy is a function evidently designed for use with
> fixed-length character buffers, not the null-terminated strings that
> are semi-standard in C. That makes one wonder why strncpy is included
> with functions that are intended for use with null-terminated strings,
> and why there is no "safe" copying function for the latter.

The first question has, in effect, already been answered: the behavior
of strncpy() was that required for writing entries in UNIX directories.
It was natural to put it in the library so that programs could use it
for other purposes, and once it became common for them to do so, it had
to remain there forever for compatibility.

(One example of an "other purpose", by the way, is strncpy(dest, "", n),
which puts all zero bits in the destination without needing an ifdef to
choose bzero() or memset().  I make no claim that it's fast or readable,
but it's certainly legitimate.)

As to the second question, there IS a simple way to get the effect of

		if (strlen (src) > n) {
			strncpy(dest, src, n);
			dest[n] = '\0';
		} else
			strcpy(dest, src);

(where we don't want to take the time to fill the destination with
trailing nulls in the "else" case, otherwise we could just use strncpy).
That way is:

		sprintf (dest, "%.*s", n, src);

(or if n is known to be, say, 17, then sprintf (dest, "%.17s", src);).

In practice this, too, may of course be too slow.  But then, so may strcpy().

-- 
Mark Brader, Toronto		"Mark is probably right about something,
utzoo!sq!msb, msb@sq.com	 but I forget what"	-- Rayan Zachariassen

This article is in the public domain.

ellisond@phobos.UUCP (Dell Ellison) (01/23/90)

In article <11616@csli.Stanford.EDU>, poser@csli.Stanford.EDU (Bill Poser) writes:
> In article <000003Q@cdis-1.UUCP> tanner@cdis-1.UUCP (Dr. T. Andrews) writes:
> >Your consideration of strcpy()/strncpy() is more than a little
> >reminiscent of a man who has in hand a claw hammer and a ball peen
> >hammer, and who wishes to know why he can't pull nails with the
> >latter.
> 
> Not really. It's more like the question of why the carpentry shop
> has a ball peen hammer (used for metal working) and doesn't have
> a claw hammer. strncpy is a function evidently designed for use with
> fixed-length character buffers, not the null-terminated strings that
> are semi-standard in C. That makes one wonder why strncpy is included
> with functions that are intended for use with null-terminated strings,
> and why there is no "safe" copying function for the latter.
                                                                      
Actually, the reason why they are 'null-terminated strings' is because
they are variable in length.  If you are using strncpy then you want an
exact number of characters.  If you want n characters then you don't
want to get n+1 characters.  Besides, in C, nothing is completely safe.
I think we should all take responsability for our own strings. :-)    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    
                                                                    

poser@csli.Stanford.EDU (Bill Poser) (01/23/90)

In article <48314938.f69e@phobos.UUCP> ellisond@phobos.UUCP (Dell Ellison) writes:
>                                                                      
>Actually, the reason why they are 'null-terminated strings' is because
>they are variable in length.  If you are using strncpy then you want an
>exact number of characters.

I think this reflects a confusion between variability in the size of
strings and variability in the size of string containers. (I don't
know if this is a standard term, but Bron & Dijkstra use it in
a recent SIGPLAN notices.) What strncpy is good for (or would be
good for if it null-terminated) is making sure that the copy does
not overflow the string container. The container may be (and usually is)
used for strings of variable length, and the strings copied may
be of variable length. At least in my experience, it is generally
not the case that one is trying to truncate the source string to
exactly N characters - rather, one is trying to copy as much of the
source string as will fit into the target container.

Note also that strncpy does not copy "an exact number of characters".
It copies up to N characters, stopping at the first null. In other
words, it observes the null-termination convention for the source
string, and does so for the target string if it isn't too long.
That's why it is a bastard function - it is designed to work with
the null-termination convention but does not guarantee closure.

daveh@marob.masa.com (Dave Hammond) (01/23/90)

In article <11864@csli.Stanford.EDU> poser@csli.stanford.edu writes:
>Note also that strncpy does not copy "an exact number of characters".
>It copies up to N characters, stopping at the first null.

From the Xenix manual page for string(S):

char *strncpy(S1,S2,N)
...
strncpy copies exactly N characters, truncating or null-padding S2; the
target may not be null-terminated if the length of S2 is N or more.
...

--
Dave Hammond
daveh@marob.masa.com
uunet!masa.com!marob!daveh

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (01/23/90)

In article <25BC3A32.3F5B@marob.masa.com> daveh@marob.masa.com (Dave Hammond) writes:

| From the Xenix manual page for string(S):
| 
| char *strncpy(S1,S2,N)
| ...
| strncpy copies exactly N characters, truncating or null-padding S2; the
| target may not be null-terminated if the length of S2 is N or more.
| ...

  Regardless of what the manual says, it does not seem to work that way.
The copy is *at most* N characters, but will stop is a null byte is
encountered. You can verify this by placing data after the null byte in
the source string and checking that it is not copied.

  I believe the procedure which functions as described is memcpy().
-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
            "Stupidity, like virtue, is its own reward" -me

peter@ficc.uu.net (Peter da Silva) (01/23/90)

> That's why it is a bastard function - it is designed to work with
> the null-termination convention but does not guarantee closure.

What it does is provide the most generally useful facility. If it always
null-terminated, it couldn't be used for copies into a known fix-sized
buffer. And since you know the length, you can always null-terminate
the string yourself.
-- 
 _--_|\  Peter da Silva. +1 713 274 5180. <peter@ficc.uu.net>.
/      \
\_.--._/ Xenix Support -- it's not just a job, it's an adventure!
      v  "Have you hugged your wolf today?" `-_-'

brnstnd@stealth.acf.nyu.edu (01/24/90)

In article <ZC91DJ4xds13@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
> > That's why it is a bastard function - it is designed to work with
> > the null-termination convention but does not guarantee closure.
> What it does is provide the most generally useful facility.

No.

> If it always
> null-terminated, it couldn't be used for copies into a known fix-sized
> buffer.

Huh? strncpy(s1,s2,n) should work like the current strncpy(s1,s2,n)
followed by s1[n - 1] = '\0' if necessary. That's a copy into a known
fixed-size buffer, preserving null termination.

> And since you know the length, you can always null-terminate
> the string yourself.

Since I do, in fact, always null-terminate the string myself, I'd prefer
that strncpy do the job for me.

---Dan

poser@csli.Stanford.EDU (Bill Poser) (01/24/90)

In article <25BC3A32.3F5B@marob.masa.com> daveh@marob.masa.com
(Dave Hammond) writes:

>From the Xenix manual page for string(S):
>
>char *strncpy(S1,S2,N)
>...
>strncpy copies exactly N characters, truncating or null-padding S2; the
>target may not be null-terminated if the length of S2 is N or more.

The manual page does indeed say that strncpy(3) copies exactly
N characters, but as William Davidsen has pointed out, the manual,
at least on some systems, is wrong. Here is a little test program.

#include <stdio.h>
main()
{
   char src[20];
   char tgt[20];

   sprintf(src,"%s","abcdefg");
   printf("src = %s\n",src);
   src[3] = '\0';
   printf("src = %s\n",src);
   strncpy(tgt,src,5);
   printf("tgt = %s\n",tgt);

   exit(0);
}

It puts the string "abcdefg" (7 characters plus a null) into src
and prints it out. Then it assigns a null to the 4th position, overwriting
the "d" and prints it out. Then it strncpy's it to tgt, requesting a 5
character copy, and prints the result. I just compiled and ran this program
on: (a) a SUN 4 running SUN-OS; (b) an HP 9000/350 running HP-UX, and
(c) an HP 9000/320 running 4.3 Tahoe BSD. On all three the result was that
the null byte terminated the copy. Here is the script from the HP 350:

Script started on Tue Jan 23 14:58:27 1990
crystals-[1]/user2/poser
: foo
src = abcdefg
src = abc
tgt = abc
crystals-[2]/user2/poser
: 
script done on Tue Jan 23 14:58:33 1990

If strncpy copied exactly N characters, the third output line should
read: tgt = abcde
On all three systems the manual says that strncpy copies exactly N
characters, and on all three it is wrong.

poser@csli.Stanford.EDU (Bill Poser) (01/24/90)

	As a further clarification of what strncpy(3) actually does,
let me point out that although it only COPIES up to the null byte in the
source string, it WRITES exactly N characters into the target string,
padding with nulls if necessary. So the bit about null-padding in the manual
is correct - what is erroneous is the bit about copying. To see this,
try a program like this:

#include <stdio.h>
main()
{
   char src[20];
   char tgt[20];

   sprintf(src,"%s","abcdefg");
   sprintf(tgt,"%s","abcdefg");
   printf("src = %s\n",src);
   printf("tgt = %s\n",tgt);
   src[3] = '\0';
   printf("src = %s\n",src);
   strncpy(tgt,src,5);
   printf("tgt = %s\n",tgt);
   printf("tgt[4] = %c\n",tgt[4]);
   printf("tgt[5+] = %s\n",&(tgt[5]));
   exit(0);
}

It initializes both src and tgt to "abcdefg", assigns a null to src[3],
does the strncpy, and then prints the various pieces of tgt. The
result is:

Script started on Tue Jan 23 15:34:49 1990
crystals-[1]/user2/poser
: foo
src = abcdefg
tgt = abcdefg
src = abc
tgt = abc
tgt[4] = 
tgt[5+] = fg
crystals-[2]/user2/poser
: 
script done on Tue Jan 23 15:34:57 1990

Notice that the fifth character of tgt, originally "e", has been
overwritten by a null, but that the remainder of tgt is unaffected.
So, what strncpy does is to COPY up to the null byte or N characters,
whichever comes first, and then null-pad out to the N character limit.

poser@csli.Stanford.EDU (Bill Poser) (01/24/90)

Just a note to point out that the test of printf-ing the result of a
strncpy is not sufficient to show that it stops copying at the null byte
(contrary to my previous statement). It is necessary to check what character
is in the target string after the null. As my previous message shows, this
is in fact a null, showing that copying does stop at the null byte.

john@stat.tamu.edu (John S. Price) (01/24/90)

In article <11881@csli.Stanford.EDU> poser@csli.stanford.edu (Bill Poser) writes:
>
>The manual page does indeed say that strncpy(3) copies exactly
>N characters, but as William Davidsen has pointed out, the manual,
>at least on some systems, is wrong. Here is a little test program.
>
>#include <stdio.h>
>main()
>{
>   char src[20];
>   char tgt[20];
>
>   sprintf(src,"%s","abcdefg");
>   printf("src = %s\n",src);
>   src[3] = '\0';
>   printf("src = %s\n",src);
>   strncpy(tgt,src,5);
>   printf("tgt = %s\n",tgt);
>
>   exit(0);
>}
>
>It puts the string "abcdefg" (7 characters plus a null) into src
>and prints it out. Then it assigns a null to the 4th position, overwriting
>the "d" and prints it out. Then it strncpy's it to tgt, requesting a 5
>character copy, and prints the result. I just compiled and ran this program
>on: (a) a SUN 4 running SUN-OS; (b) an HP 9000/350 running HP-UX, and
>(c) an HP 9000/320 running 4.3 Tahoe BSD. On all three the result was that
>the null byte terminated the copy. Here is the script from the HP 350:
>
>Script started on Tue Jan 23 14:58:27 1990
>crystals-[1]/user2/poser
>: foo
>src = abcdefg
>src = abc
>tgt = abc
>crystals-[2]/user2/poser
>: 
>script done on Tue Jan 23 14:58:33 1990
>
>If strncpy copied exactly N characters, the third output line should
>read: tgt = abcde
>On all three systems the manual says that strncpy copies exactly N
>characters, and on all three it is wrong.

Every manual I read says this:
"... If the string pointed to by the source has fewer than count
characters, nulls are added to the end of dest until count characters 
have been copied." -- C - The Complete Reference.

"... strncpy(s,t,n)    copy exactly n characters; null pad if necessary"
 -- Unix Programming Environment

The key to this is the way C, or for that matter, ASCIIZ, string
convention works.  A series of characters followed by a NULL is
considered a string.  So, if you have a string

foo[] = "This is a test of the Emergency Broadcast System.";

and say

foo[14] = NULL;

You are CHANGING THE STRING LENGTH.  It is now 14 characters long,
instead of 49.  

back to the example in question...

The only was strncpy can know if the source has fewer than count (in the
program example 5) characters is if it's null terminated or not.  So, when
you say 

src[3]=0;

you, by definition of the ASCIIZ convention, have shortened the string
to 3 characters, namely "abc".  When strncpy(tgt,src,5) gets a pointer to

"abc\000efg"

for the source, all it considers to be the STRING is

"abc"

and that is all it copies to tgt.  It pads tgt with NULLs up to N, 
the number of characters specified to copy.

You have to remember that all of these are STRING FUNCTIONS, not
block memory move functions.  If you wanted to copy the 5 bytes
from src to tgt, do

memcpy(tgt,src,5);

But, printf would still print out "abc" for tgt, because it
is NULL terminated.  Only difference is that tgt[4]=='e' now, 
instead of NULL.

strncpy() is acting exactly to the manuals specs.  When it says
is will copy EXACTLY 5 characters from the STRING src to the
destination STRING tgt, it copys 5 characters from the string.
Since strings are NULL terminated, strncpy has to assume
that anything after the NULL is garbage, and not part
of the string.  It assumes that tgt will have N bytes allocated
to it, but doesn't assume that src has at least N bytes.

If src is larger than N, then it copys N characters to tgt.
It doesn't NULL terminate tgt because it can't assume that
tgt is N+1 bytes long.

Just to clear things up...

--------------------------------------------------------------------------
John Price                   |   It infuriates me to be wrong
john@stat.tamu.edu           |   when I know I'm right....
--------------------------------------------------------------------------

john@stat.tamu.edu (John S. Price) (01/24/90)

In article <11882@csli.Stanford.EDU> poser@csli.stanford.edu (Bill Poser) writes:
>...[stuff deleted]...
>So, what strncpy does is to COPY up to the null byte or N characters,
>whichever comes first, and then null-pad out to the N character limit.

This is exactly right.  Strncpy copys exactly N characters from
source to destination.  If N > strlen(source) then strncpy
cannot assume that the bytes after the NULL in source are
part of the string.  The manuals aren't ambiguous if you
take into consideration the definition of a string.


--------------------------------------------------------------------------
John Price                   |   It infuriates me to be wrong
john@stat.tamu.edu           |   when I know I'm right....
--------------------------------------------------------------------------

peter@ficc.uu.net (Peter da Silva) (01/24/90)

In article <9683@stealth.acf.nyu.edu> brnstnd@stealth.acf.nyu.edu (Dan Bernstein) writes:
> > If it always
> > null-terminated, it couldn't be used for copies into a known fix-sized
> > buffer.

> Huh? strncpy(s1,s2,n) should work like the current strncpy(s1,s2,n)
> followed by s1[n - 1] = '\0' if necessary. That's a copy into a known
> fixed-size buffer, preserving null termination.

But what if you want to keep all !n! bytes of information? Then you have
to make your buffer 1 byte larger. Which can be a pain in a fixed
structure.

Let's put it this way. It's easy to implement *your* strncpy in the *real*
strncpy, but it's not even possible to do it the other way round.

> Since I do, in fact, always null-terminate the string myself, I'd prefer
> that strncpy do the job for me.

Since I don't, in fact, always null-terminate the string myself, I'm glad it 
doesn't.

Meditate on struct utmp.
-- 
 _--_|\  Peter da Silva. +1 713 274 5180. <peter@ficc.uu.net>.
/      \
\_.--._/ Xenix Support -- it's not just a job, it's an adventure!
      v  "Have you hugged your wolf today?" `-_-'

dave@motto.UUCP (David Brown) (01/24/90)

In article <4128@helios.TAMU.EDU> john@stat.tamu.edu (John S. Price) writes:
>Every manual I read says this:
>"... If the string pointed to by the source has fewer than count
>characters, nulls are added to the end of dest until count characters 
>have been copied." -- C - The Complete Reference.
>
>"... strncpy(s,t,n)    copy exactly n characters; null pad if necessary"
> -- Unix Programming Environment
>

We found this useful when dealing with the keys of ISAM files under VMS.
If the key was a C string, we used strncpy() to copy it rather than
strcpy().  This guaranteed that the bytes following the '\0' were all
zeroes.  This was important because the filesystem compared all bytes of
the key.

If we had used strcpy(), two keys which were the same string value could
be different as far as the filesystem was concerned, because of garbage
following the '\0'.

 -----------------------------------------------------------------------------
|  David C. Brown	    |  uunet!mnetor!motto!dave			      |
|  Motorola Canada, Ltd.    |  416-499-1441 ext 3708			      |
|  Communications Division  |  "Of course I'm above average!  Who isn't?"     |
 -----------------------------------------------------------------------------

rli@buster.irby.com (Buster Irby) (01/25/90)

brnstnd@stealth.acf.nyu.edu writes:

>Since I do, in fact, always null-terminate the string myself, I'd prefer
>that strncpy do the job for me.

You have obviously never worked with any vendor supplied software
which used non null-terminated buffers.  For example, when you
access a string data field under Unify, there is no null
termination at the end of the field, because the string fields
are fixed length.  It is not necessary to terminate fixed length
items with any kind of special marker.  Special markers, such as
the null character, are only useful when dealing with variable
length data.  Furthermore, in any database, I would consider it
very inefficient to store null terminators.

-- 
Buster Irby  buster!rli