strcpy overlapping memory

B

BartC

Eric Sosman said:
Eric Sosman said:
On 12/11/2010 5:53 PM, BartC wrote:
[...] an array has 0 elements, therefore
it's
pointer is 0 -- where would it point to otherwise?

You have an array of zero elements? In a C program? How did
you manage that? Was this before or after you squared the circle?

It was just after I wrote this:
[...]
int *array=0;
[...]
The array is zero length at the time of the first print_intarray() call.

"The array?" What array? Perhaps you should read Section 6
of the FAQ. (If you've already read it, re-read it. This time,
read for comprehension.)

None of the section headings leap out at me. Perhaps you mean the bit about
arrays and pointers being identical, so that an array needs to be a valid
pointer to something, and NULL is not allowed.

Well, OK. In that case it's necessary to use a little bit of abstraction and
use a slightly higher level of array concept. For example, the 'intarray' I
created in that code example.

For my intarrays, I *can* have an array of length zero. The pointer value is
not critical, since it should not need to be dereferenced (unlike an empty
string which needs to get at the zero terminator). It can be NULL as I've
used, or perhaps point into valid memory to create a slice of 0 to N
elements, depending on intarray length. Or whatever.

As shown, I can use a function such print_intarray to display an array of 0
to N elements.

I could also write one called append_intarray to add an element to an
intarray, increasing it's length from 0 to N elements, to 1 to N' elements.

So such an 'array' can be perfectly well-behaved even when it's empty, even
though it may not exactly correspond to C's official definition of an array,
whatever that is. (And there's a guy over on comp.lang.misc who insists that
C doesn't have arrays at all..)
 
K

Keith Thompson

BartC said:
Except that many C library functions don't seem to recognise the concept of
No String (as personified by a NULL argument where a char* one is expected);
they assume it IS a pointer to a string, empty or otherwise.

They *require* that the argument (for example, the argument to
strlen()) is a pointer to a string.

The idea that a null pointer is not a pointer to a string is implicit
in the Standard's definition of the phrase "pointer to a string"
(C99 7.1.1p1). The distinction is between values that you *can*
pass to strlen(), and values that you *can't* pass to strlen()
(or, more precisely, that you can pass but the standard doesn't
define the behavior).

There's no need for strlen() to make that distinction itself.
It's entirely the responsibility of the caller, just as it's the
caller's responsibility not to call strlen() with a pointer that's
just been free()'d.

A pointer value may be valid or invalid depending on the context in
which it's used. A null pointer value is perfectly valid on the RHS of
an assignment, but not as the operand of a unary "*". A pointer to
a struct object that's been converted to void* is valid as an argument
to memset(), but not as an argument to strlen().

I suppose that having string functions treat null pointers as if they
were pointers to empty strings would be more convenient in some cases
(though it could impose extra overhead where the caller has taken care
to pass a non-null pointer), but in my opinion it makes for a more
consistent mental model.

If you had a function that took an int* argument, would you want it
to treat a null pointer as if it pointed to an int with the value 0?

Admittedly, the difference there is that you can pass int arguments
directly, so there's no need to use a pointer if you just want the
value. If C were able to treat strings as first-class objects (as some
languages do), we probably wouldn't be having this debate.
 
J

JohnF

The China Blue and the Gray said:
I have my own string equals which is
a==b || a && b && *a==*b && strcmp(a, b)==0
which handles NULLs just the way I want

Just curious, can you be 100% sure the order of operations
will compile to handle nulls the way I assume you want (i.e.,
the a&&b part will >>first<< be false if either is null,
so strcmp won't be evaluated)? Personally, I usually
try to guarantee order, doing what you're doing with
( a==b? 1 : (a&&b? (*a==*b? (strcmp(a,b)): 0) : 0) )
instead. A little awkward, maybe, but hidden in a macro
and no doubt about what happens when.
 
B

Barry Schwarz

``*a==*b'' is redundant (it's implied by ``strcmp(a,b)==0'').

The first expression evaluates only the first character in each
string. The second evaluates as many characters as exist in the
shorter string.
 
B

BartC

Barry Schwarz said:
The first expression evaluates only the first character in each
string. The second evaluates as many characters as exist in the
shorter string.

Including the first in each string; that's why the *a==*b can be considered
redundant.

But I'd imagine it's just a slightly faster way of dealing with strings that
are obviously unequal (provided they start with different characters).
 
S

Seebs

The first expression evaluates only the first character in each
string. The second evaluates as many characters as exist in the
shorter string.

Not generally; usually, it'll stop as soon as it finds a non-match,
so if *a!=*b, strcmp will exit after one compare.

-s
 
I

Ian Collins

I hate to be Contrary Harry again, but I had an experience circa 1987
that was startling. I was working with a Sun-3 workstation, wrote
my own memcpy() (just a trivial unrolled loop in C), compared it with
the
library memcpy() and discovered mine was ... much faster !!?!?!?!??!!

Delving into Sun-3 source code I found that memcpy() was a very
tiny loop in assembly, with a comment clearly stating
"optimized for the [tiny] Sun-2 instruction cache."
Please understand that the Sun-2 was quite obsolescent by then;
indeed the Sun-4 was soon to arrive.

I'm speaking of memcpy() for heaven's sakes! If one is supposed to
remember to optimize *any* function, that function is memcpy()!!!

In MacOS X, there is a small area of memory that is filled at boot
time with processor specific code for a handful of functions. Some are
functions like atomic increment, which may need processor specific
code to work correctly, others are functions like memset and memcpy
for which you want processor specific optimised code.

So if you call memcpy or memset from the Standard C library on MacOS
X, you will be executing hand optimised assembler code for the
particular processor which is running your code. And the one on my Mac
is quite bizarre and very, very, fast.

Some compilers (Sun Studio for example) will inline similarly optimised
code at appropriate optimisation levels.
 
T

Tim Rentsch

James Dow Allen said:
I'm surprised too when I look at a typical memcpy() implementation ...
...
But I trust the library programmers; that they did some thinking ...

I hate to be Contrary Harry again, [snip]

Oh who are you kidding? You _love_ being Contrary Harry. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,083
Messages
2,570,589
Members
47,211
Latest member
JaydenBail

Latest Threads

Top