[comp.sys.atari.st] more on strncpy

depeche@quiche.cs.mcgill.ca (Sam Alan EZUST) (12/14/89)

Here is a private letter I wanted to send but it got bounced, 
but I realize it should be posted publicly for some of its
content anyway.

>>> DATA
<<< 554 <john%stag.UUCP%uunet.UUCP%dynasoft@Larry.McRCIM.McGill.EDU>... Remote protocol error: Bad file number
554 john%stag.UUCP%uunet.UUCP%dynasoft@Larry.McRCIM.McGill.EDU... Service unavailable


[In message "Re: laser C question" on Dec 13, John Stanley writes:]
: [in my message I wrote:] 
: > Since there is no mem.h library of routines, I use strncpy to copy the
: > contents of one-dimensional arrays.
: 
:   Since strncpy doesn't copy <n> bytes but rather <n> bytes OR until it
: finds the 1st null (zero) byte in the array, using strncpy to replace
: blkcpy or memcpy isn't going to work.  If it has worked so-far, it's only
: because Laser C uses an incorrect implementation of strncpy or because
: you've been Very-Very lucky....

no, actually. This little fact was something I knew a little while ago
but totally forgot about until two days ago, while I was agonizing over
the strangest bug for four damned hours and finally found it after
exhausting every other goddamned possibility... Too bad your letter didn't
come two days earlier, but that's not your fault :-)..

:   Moving one, two, or fifty dimensional arrays is all the same to C.
: It's just a destination address, a source address, and the number of
: bytes to move...


:   I can send you one that's written for Alcyon/Sozobon C in assembly.
: It's quite fast but you'd probably have to modify it a little to be
: compatable with Lazer C.  I could also send you a similar block-move
: function written entirely in C (it just wouldn't be quite-as-fast).

someone already sent me dlibs memcpy which I believe is what is used
in Sozobon.... However, I don't have an assembler and am not too
much of an expert in it anyway, so I couldn't get it installed on
my system without help.


:   Alternately, does Lazer C allow copying structures using a simple
: assignment?  <struct2> = <struct1>;  If so, what I've ocassionaly used in
: situations like yours is to define a struct containing the array and
: moved copys of the array arround by just using assignments...

that's a good idea. I should try it. I didn't think it was possible though,
as struct names are just pointers to memory locations of data, just
like arrays, and you can address the 5th byte of a structure with
*(structname+5) just like arrays.

 in reply to my using strncpy for multidimension arrays not working,

:   Why won't it?  Ignoring for the moment that strncpy isn't a blkcpy or
: memcpy, what's wrong with specifiying &array[0][0] as the address and
: using the size of the entire array (assuming it's smaller than 64k bytes)
: as the length?

I think I tried it and got a compiler error.. I could be mistaken, but
I passed it just 

array

instead of

&(array[0][0])
since I thought the two were equivalent pointers...


:   I'm trying...  What you wrote makes it sound like you've been making
: some bad guesses so far so it may take a bit of work to get your program
: working the way you want it to...  What are you writing anyway?

you are exactly right. However, I got it working now via the brute-force
loop-of-assign statements. If I can get dlibs installed properly on
Laser C (and I am having trouble, as you will soon see in one of 
my messages posted on c-s-a-st which I posted today), I will then
translate them all into memcpy's.

:   .. although, it would be a real-good-idea if you posted a note on the
: net mentioning that strncpy doesn't move <n> bytes so other beginning
: programmers who see your message won't think that it's a correct
: substitution....

ok.. I shall. Thanks for your help/reply!!



-- 
S. Alan Ezust                                   depeche@calvin.cs.mcgill.ca
McGill University Department of Computer Science - Montreal, Quebec, Canada

dal@syntel.mn.org (Dale Schumacher) (12/16/89)

[depeche@quiche.cs.mcgill.ca (Sam Alan EZUST) writes...]
> 
> [In message "Re: laser C question" on Dec 13, John Stanley writes:]
[...lots deleted...]
> :   .. although, it would be a real-good-idea if you posted a note on the
> : net mentioning that strncpy doesn't move <n> bytes so other beginning
> : programmers who see your message won't think that it's a correct
> : substitution....
> 
> ok.. I shall. Thanks for your help/reply!!
> 
> -- 
> S. Alan Ezust                                   depeche@calvin.cs.mcgill.ca
> McGill University Department of Computer Science - Montreal, Quebec, Canada

First, a note about strncpy().  The ANSI standard (yeah, I know, "proposed")
describes strncpy() like this:

	The 'strncpy' function copies not more than 'n' characters
	(characters that follow a null character are not copied) from
	the array pointed to by 's2' to the array pointed to by 's1'.[121]
	If copying takes place between objects that overlap, the behaviour
	is undefined.
	
	If the array pointed to by 's2' is a string that is shorter than
	'n' characters, null characters are appended to the copy in the
	array pointed to by 's1', until 'n' characters in all have been
	written.

[121:	Thus, if there is no null character in the first 'n' characters of
	the array pointed to by 's2', the result will not be null-terminated]

Secondly, the dLibs version is (slightly) broken according that the above
description.  It only copies up to the first null character, or 'n'
characters total, and does NOT pad the copy will null characters up to 'n'.
This almost never causes a problem, since the destination is null-terminated
in that case, but I thought I should point it out.  It's also easy to fix,
but I'll leave that as an exercise for the reader :-)

\\   /  Dale Schumacher                         399 Beacon Ave.
 \\ /   (alias: Dalnefre')                      St. Paul, MN  55104-3527
  ><    ..!nic.mr.net!bungia.mn.org!syntel!dal  United States of America
 / \\   "The power of accurate observation is commonly called cynicism
/   \\   by those who have not got it." -George Bernard Shaw

kirkenda@.cs.pdx.edu (Steve Kirkendall) (12/16/89)

(I would have mailed this, but none of the machines around here have ever heard
 of Canada before.  Or any other country either.)

In article <1870@calvin.cs.mcgill.ca> depeche@calvin.cs.mcgill.ca (Sam Alan EZUST) writes:
>someone already sent me dlibs memcpy which I believe is what is used
>in Sozobon.... However, I don't have an assembler and am not too
>much of an expert in it anyway, so I couldn't get it installed on
>my system without help.

Okay, here's one in C:

	memcpy(dest, src, count)
		register char	*dest;	/* destination address */
		register char	*src;	/* source address */
		register int	count;	/* number of bytes to copy */
	{
		while (--count >= 0)
			*dest++ = *src++;
	}

This can copy up to 32767 bytes at a time.  It isn't very fast, though.

>:   Alternately, does Lazer C allow copying structs using a simple
>: assignment?  <struct2> = <struct1>;  If so, what I've ocassionaly used in
>: situations like yours is to define a struct containing the array and
>: moved copys of the array arround by just using assignments...
>
>that's a good idea. I should try it. I didn't think it was possible though,
>as struct names are just pointers to memory locations of data, just
>like arrays, and you can address the 5th byte of a struct with
>*(structname+5) just like arrays.

No.  A struct variable is not treated as a pointer.  If you do something
like this...

	struct dirent	d;
	somefunc(d);

... then somefunc will be called with a copy of d as its argument,
and the copy will be sizeof(struct dirent) bytes long, on the stack!
It does *not* pass a pointer to d.  Laser C can handle struct assignments.

And any attempt to add an int to a struct should net you an error message.

> in reply to my using strncpy for multidimension arrays not working,
>
>:   Why won't it?  Ignoring for the moment that strncpy isn't a blkcpy or
>: memcpy, what's wrong with specifiying &array[0][0] as the address and
>: using the size of the entire array (assuming it's smaller than 64k bytes)
>: as the length?
>
>I think I tried it and got a compiler error.. I could be mistaken, but
>I passed it just 
>
>array
>
>instead of
>
>&(array[0][0])
>since I thought the two were equivalent pointers...

They both point to the same place in memory, but they are pointers to different
types of data.  The first form is a pointer to an array (a vector, actually --
the first column of your two-dimensional array).  The second is a pointer to a
single element.  The distinction isn't very important when you're using the
expression as an argument to memcpy(), though.

The simplest way to copy a two-dimensional array with memcpy() is:

	memcpy(destarray, srcarray, sizeof srcarray);

Some compilers may complain about this since the first two arguments are not
of type (char *).  You may wish to coerce them to get rid of the warning and
improve portability, at the expense of readability...

	memcpy((char *)destarray, (char *)srcarray, sizeof srcarray);
--------------------------------------------------------------------------------
Steve Kirkendall, kirkenda@cs.pdx.edu, uunet!tektronix!psueea!jove!kirkenda

john@dynasoft.UUCP (John Stanley) (12/18/89)

[kirkenda@.cs.pdx.edu (Steve Kirkendall) writes...]
> 
> In article <1870@calvin.cs.mcgill.ca> depeche@calvin.cs.mcgill.ca (Sam Alan EZUST) writes:
>>someone already sent me dlibs memcpy which I believe is what is used
>>in Sozobon.... However, I don't have an assembler and am not too
>>much of an expert in it anyway, so I couldn't get it installed on
>>my system without help.
> 
> Okay, here's one in C:
> 
> 	memcpy(dest, src, count)
> 		register char	*dest;	/* destination address */
> 		register char	*src;	/* source address */
> 		register int	count;	/* number of bytes to copy */
> 	{
> 		while (--count >= 0)
> 			*dest++ = *src++;
> 	}
> 
> This can copy up to 32767 bytes at a time.  It isn't very fast, though.

  Actualy, it can copy up to 65535 bytes if you change:

		while (--count >= 0)
	into
 		while (count-- != 0)

  While the parameter passed to memcpy is usualy documented to be just an
int, it's not uncommon for versions of memcpy to treat the count variable
as an unsigned integer instead which doubles the amount to memory that
can be moved with a single call...

  (Before you use this, be sure your code isn't going to have to deal
with copying negative numbers of bytes... only 1/2 :^)

---
John Stanley <dynasoft!john@stag.UUCP>
Software Consultant / Dynasoft Systems

john@dynasoft.UUCP (John Stanley) (12/18/89)

[depeche@quiche.cs.mcgill.ca (Sam Alan EZUST) writes...]
[.. responding to email I sent to him ..]

> :   Alternately, does Lazer C allow copying structures using a simple
> : assignment?  <struct2> = <struct1>;  If so, what I've ocassionaly used in
> : situations like yours is to define a struct containing the array and
> : moved copys of the array arround by just using assignments...
> 
> that's a good idea. I should try it. I didn't think it was possible though,
> as struct names are just pointers to memory locations of data, just
> like arrays,

  Nope.  A struct name is the name of a structure.  It is -not- a pointer
even though it has an address that you can obtain by using: &structname
(Note that the address you obtain (unless you cast it or store it into a
pointer of some other type) still "knows" that it's pointing to a struct
so if you use *(&structname) it references the original structure, not
just the 1st byte in the structure.

  *(unsigned char *)(&structname) would give you the structures 1st byte...

> and you can address the 5th byte of a structure with
> *(structname+5) just like arrays.

  Nope....  *(structname+5) is an illegal construct.  You can't increment
a structure itself and contrary to your assumption, a structname is -not-
the same as a pointer to a structure.

  On the other hand, ((&structname)+5) (which is different) would point
to a location 5 STRUCTURES higher in memory than &structname.  In C, any
addition to a pointer is taken as increasing the pointer by (the value
added multiplied by the size of the object being pointed at (in this case
a structure)).  This sometimes causes confuses because many people
normaly only deal with arrarys of characters (so the sizeof object == 1).

  Example:

	struct foo
		{
		int foo_1[32][100];
		};

	foocpy()
		{
		struct foo src, dst;

		/* if your compiler allows structure assignment, */
		/* the next line should copy an array 32 x 100   */
		/* integers long with a single assignment...     */

		dst = src;

		/* individual elements would be referenced as... */

		src.foo_1[23][7] = 2619;
		}
 
> you are exactly right. However, I got it working now via the brute-force
> loop-of-assign statements. If I can get dlibs installed properly on
> Laser C (and I am having trouble, as you will soon see in one of 
> my messages posted on c-s-a-st which I posted today), I will then
> translate them all into memcpy's.

  Good luck.  You may still want to consider using struct assignments
since I've been told Lazer-C does support them...

> :   .. although, it would be a real-good-idea if you posted a note on the
> : net mentioning that strncpy doesn't move <n> bytes so other beginning
> : programmers who see your message won't think that it's a correct
> : substitution....
> 
> ok.. I shall. Thanks for your help/reply!!

  You're welcome...

> -- 
> S. Alan Ezust                                   depeche@calvin.cs.mcgill.ca
> McGill University Department of Computer Science - Montreal, Quebec, Canada

---
John Stanley <dynasoft!john@stag.UUCP>
Software Consultant / Dynasoft Systems