Qry : Behaviour of fgets -- ?

P

Peter J. Holzer

[snips]

char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );

This *won't* produce a proper null terminated string in dst?

You don't *tell* strncpy to produce a zero-terminated string here.

Sure I do - by specifying a destination buffer larger than the source.

If you can be sure of that there is no advantage in using strncpy over
strcpy.

I said no such thing. Learn to read. Here, I'll quote it for you:

"...but as a library function this one will, presumably, be "more
optimal" than a loop..."

Which is a strawman, because a loop is not the only alternative to
strncpy.

hp
 
R

Richard Heathfield

Peter J. Holzer said:
[snips]

char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );

This *won't* produce a proper null terminated string in dst?

You don't *tell* strncpy to produce a zero-terminated string here.

Sure I do - by specifying a destination buffer larger than the source.

If you can be sure of that there is no advantage in using strncpy over
strcpy.

True enough, but then strncpy was not designed to be used in place of
strcpy. The strncpy function is designed for copying substrings, and it
does that job reasonably well (although, it can be argued, not as well as
memcpy does it). It is not supposed to be a safe alternative to strcpy,
which is just as well because it would do the job very badly indeed.

<snip>
 
K

Keith Thompson

Richard Heathfield said:
True enough, but then strncpy was not designed to be used in place of
strcpy. The strncpy function is designed for copying substrings, and it
does that job reasonably well (although, it can be argued, not as well as
memcpy does it). It is not supposed to be a safe alternative to strcpy,
which is just as well because it would do the job very badly indeed.

And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be. strncat(), for example, behaves
like strcat(), except that it lets you set a limit on the length of
the target string, while still guaranteeing that it will be properly
zero-terminated; similarly for snprintf().
 
R

Richard Heathfield

Keith Thompson said:
Richard Heathfield said:
[strncpy] is not supposed to be a safe alternative to
strcpy, which is just as well because it would do the job very badly
indeed.

And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be.

I don't dispute that it's a lousy name.
 
C

Charlie Gordon

Richard Heathfield said:
Keith Thompson said:
Richard Heathfield said:
[strncpy] is not supposed to be a safe alternative to
strcpy, which is just as well because it would do the job very badly
indeed.

And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be.

I don't dispute that it's a lousy name.

More precisely, it is a lousy spec for such a name.
It would have been quite natural if strncpy was specified as doing this:

/* too bad this is not real */
int strncpy(char *s, size_t size, const char *p) {
return snprintf(s, size, "%s", p);
}

But we cannot rewrite history.
Given the current and unfixable spec for strncpy, the reasonable thing to do
is deprecate its use.
 
C

Charlie Gordon

Keith Thompson said:
And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be. strncat(), for example, behaves
like strcat(), except that it lets you set a limit on the length of
the target string, while still guaranteeing that it will be properly
zero-terminated; similarly for snprintf().

Your statement holds for snprintf, but not for strncat: the num argument is
not "a limit on the target string", it is a limit on the number of
characters to copy from the source string. As such, it is no safer than
strcat itself. It does guarantee zero-termination, but can still overflow
the destination string!
 
K

Keith Thompson

Charlie Gordon said:
Your statement holds for snprintf, but not for strncat: the num argument is
not "a limit on the target string", it is a limit on the number of
characters to copy from the source string. As such, it is no safer than
strcat itself. It does guarantee zero-termination, but can still overflow
the destination string!

Ok, good point. But one could argue, I suppose, that strncat's target
string begins just after the existing string. If you know the size of
the target array and the current length of the string it contains, you
can use strncat safely.

In fact, I think a simple way to implement what strncpy() *should*
have been is to call strncat() after setting the first character of
the target array to '\0' (though since the count doesn't include the
terminating '\0' you need to watch out for off-by-one errors).
 
K

Kelsey Bjarnason

Kelsey Bjarnason said:



You are Dan Pop, and I claim my five pounds.

Would that I were. There was a dude with a head on his shoulders. Not
that there aren't a few such others about, yourself obviously included.

That said, okay, fine, I got a bit grumpy; call it an artifact of the
sudden infusion of apparent idiocy into the group. I'll spnak myself and
try to be nice, even if I do feel more like chewing their faces off than
anything.
 
P

Peter J. Holzer

Peter J. Holzer said:
[snips]
On Tue, 18 Sep 2007 20:05:10 +0200, Peter J. Holzer wrote:
char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );

This *won't* produce a proper null terminated string in dst?

You don't *tell* strncpy to produce a zero-terminated string here.

Sure I do - by specifying a destination buffer larger than the source.

If you can be sure of that there is no advantage in using strncpy over
strcpy.

True enough, but then strncpy was not designed to be used in place of
strcpy. [...]
It is not supposed to be a safe alternative to strcpy,

Exactly. That's what I was trying to explain. However, it seems I didn't
get that point across to Kelsey, and while trying to find yet another
way to explain the same thing I got a bit unfocused.

hp
 
R

Richard Bos

Douglas A. Gwyn said:
An argument for standardization is that there is a lot of
(possibly) otherwise portable C source code around that
cannot be readily ported to other platforms due to
containing such decorations. The fact that more than one
major compiler implementation added such a feature seems
to indicate that there is a practical need for it.

Possibly, but it has the same problems as #pragma: if you do not
standardise the options it controls the result is still unportable,
because one implementation's options can easily clash with another's;
but if you _do_ standardise those options, you miss the very point of
the attributes being outside the Standard's scope. In that light, you
might as well leave them as #pragma's.
That said, I'm not happy with the idea.

Neither am I.
 
D

Douglas A. Gwyn

Richard said:
but if you _do_ standardise those options, you miss the very point of
the attributes being outside the Standard's scope.

The idea is to standardize both the syntax and semantics of some
selected set of attributes.
 
D

Douglas A. Gwyn

jacob said:
Are there any papers/documents about this?

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1264.pdf
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1262.pdf

See also
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1259.htm
which refers to
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1233.pdf
which was an earlier edition of N1262.

Note that some of this is being done by the C++ standards
body, which includes several C standards members. Of
course one goal is to ensure that the feature is specified
so that we don't end up with two conflicting versions for
the different languages.
 
J

jacob navia

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1264.pdf

I had read an earlier version. It is interesting that this
document mentions almost all the __declspec constructs but
doesn't mention one I considered important and use very often:

__declspec(naked)

No, no porn :)

A function declared with this attribute will have neither
a prologue nor an epilogue, not even a "return" assembly
instruction. This allows
o To write interrupt handlers and similar in assembly
o To define aliases for functions that are already
defined.

For instance:

int __declspec(naked) function(int a) { }
int realfunction(int a)
{
// code
}

The first function is just a label in the
assembly output. It exists, however, you
can take its address, pass it around like any
other function. You can export it from the shared
object, etc etc.

Maybe the omission of that is just an oversight?
Or there is a reason?

jacob
 
W

Wojtek Lerch

....
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1264.pdf

I had read an earlier version. It is interesting that this
document mentions almost all the __declspec constructs but
doesn't mention one I considered important and use very often:

__declspec(naked)

A function declared with this attribute will have neither
a prologue nor an epilogue, not even a "return" assembly
instruction.

Could you try to translate this to standardese? What's a "prologue"?
What's an "epilogue"? What's "assembly"?
This allows
o To write interrupt handlers and similar in assembly

No it doesn't, unless your compiler also has an extension that allows you to
write in assembly. Do you think that such an extension should be
standardized, too?
o To define aliases for functions that are already
defined.

For instance:

int __declspec(naked) function(int a) { }
int realfunction(int a)
{
// code
}

This is a horrible syntax to define an alias name for a function. Do you
think it could be used for anything else, with portably defined semantics?
Maybe the omission of that is just an oversight?
Or there is a reason?

Maybe because it's impossible to specify its semantics without making a lot
of assumptions about how the compiler works?
 
C

Chris Torek

jacob navia said:
__declspec(naked) [...]
This allows
o To write interrupt handlers and similar in assembly

No it doesn't, unless your compiler also has an extension that allows you to
write in assembly. Do you think that such an extension should be
standardized, too?

(I think he means "in C", but yes, you usually need such an
extension to add some sort of "return from interrupt" instruction
at the end, of course.)
This is a horrible syntax to define an alias name for a function. Do you
think it could be used for anything else, with portably defined semantics?

It is certainly "ugly" (to me), although I have never seen a "pretty"
(to me) method. (Methods I have seen include inline assembly,
various forms of pragma, and putting various instructions in a
separate linker file. The last one is the "cleanest" in various
senses, but runs an extra risk due to the separation of the source
code and link-symbol manipulation.)
Maybe because it's impossible to specify its semantics without making a lot
of assumptions about how the compiler works?

I suspect Mr Navia will now rail against you like he does against
me, at time. :)

Seriously, as an example of what might go wrong, one should
consider the following cleaned-up assembly that is the result
of compiling the following three-line C source:

int foo(void) { return 42; }
char *bar(void) { return NULL; }
void baz(int x) { }

/* results in */

bar_: .globl bar_
ori $0,$0,$1 # register 0 contains 0, so this sets r1=0
ret # and by convention r1 holds the return value
baz_: .globl baz_
ret
foo_: .globl foo_
ori $0,#42,$1 # again, r1 = 0 | 42
ret

Note that the functions have been alphabetized -- foo() no longer
comes before bar(). (This order is "luck of the draw": not deliberate
sorting, just what comes out of a table. The point is, just as
ordinary variable declarations within a function are not actually
created "in order" in a stack frame -- or even in registers -- by
an optimizing compiler, neither are the routines output "in order".
The compiler mashes things around to suit itself, then outputs
"whatever is required", not necessarily "the obvious steps, one
instruction at a time, based on the input, read one statement at
a time".)

(Real compilers really do this, and the name-aliasing method suggested
above assumes otherwise.)
 
J

jacob navia

Chris Torek wrote:
[ functions aren't necessarily generated in the order they are defined]

You have a point here Mr Torek. The same for Mr Lerch.

This is just too compiler specific.
 
D

Douglas A. Gwyn

jacob said:
__declspec(naked)
A function declared with this attribute will have neither
a prologue nor an epilogue, not even a "return" assembly
instruction. This allows
o To write interrupt handlers and similar in assembly
o To define aliases for functions that are already
defined.

The requirements for interfacing an interrupt handler to a
C function vary across platforms; simply omitting the usual
function prologue and postlogue does not work in many cases.
(Registers need to be saved and restored, etc.) It would be
nice to have support specifically for interrupt handlers.

I'm not sure why we need aliases for functions, at least
more than can be accomplished using #define.
 
J

jacob navia

Douglas said:
The requirements for interfacing an interrupt handler to a
C function vary across platforms; simply omitting the usual
function prologue and postlogue does not work in many cases.
(Registers need to be saved and restored, etc.) It would be
nice to have support specifically for interrupt handlers.

I'm not sure why we need aliases for functions, at least
more than can be accomplished using #define.

After reflecting about this, I agree it is not a good idea to
include this stuff, as I said already in this same thread.

Aliases are needed to export the same function from a shared
object with different names, for instance. But this is also
highly system specific, so I would not propose including it
in the standard.

jacob
 
F

Flash Gordon

Douglas A. Gwyn wrote, On 25/09/07 15:24:
The requirements for interfacing an interrupt handler to a
C function vary across platforms; simply omitting the usual
function prologue and postlogue does not work in many cases.
(Registers need to be saved and restored, etc.) It would be
nice to have support specifically for interrupt handlers.

Agreed. I would vote for __interrupt or __interrupt(N) if support for
interrupts where to be added, then leave it up to the compiler to do the
right thing whatever that is.
I'm not sure why we need aliases for functions, at least
more than can be accomplished using #define.

I can't see any good use for function aliases either.
 

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

No members online now.

Forum statistics

Threads
474,091
Messages
2,570,605
Members
47,225
Latest member
DarrinWhit

Latest Threads

Top