From: Cameron Simpson on
On 30Jun2010 12:19, Paul Rubin <no.email(a)nospam.invalid> wrote:
| Cameron Simpson <cs(a)zip.com.au> writes:
| > The original V7 (and probably earlier) UNIX filesystem has 16 byte directory
| > entries: 2 bytes for an inode and 14 bytes for the name. You could use 14
| > bytes of that name, and strncpy makes it effective to work with that data
| > structure.
|
| Why not use memcpy for that?

Because when you've pulled names _out_ of the directory structure they're
conventional C strings, ready for conventional C string mucking about:
NUL terminated, with no expectation that any memory is allocated beyond
the NUL.

Think of strncpy as a conversion function. Your source is a conventional
C string of unknown size, your destination is a NUL padded buffer of
known size. "Copy at most n bytes of this string into the buffer, pad
with NULs."

Cheers,
--
Cameron Simpson <cs(a)zip.com.au> DoD#743
http://www.cskk.ezoshosting.com/cs/

We had the experience, but missed the meaning. - T.S. Eliot
From: Lawrence D'Oliveiro on
In message <mailman.2369.1277870727.32709.python-list(a)python.org>, Michael
Torrie wrote:

> Okay, I will. Your code passes a char** when a char* is expected.

No it doesn't.

> Consider this variation where I use a dynamically allocated buffer
> instead of static:

And so you misunderstand the difference between a C array and a pointer.
From: Michael Torrie on
On 06/30/2010 06:36 PM, Lawrence D'Oliveiro wrote:
> In message <mailman.2369.1277870727.32709.python-list(a)python.org>,
> Michael Torrie wrote:
>
>> Okay, I will. Your code passes a char** when a char* is expected.
>
> No it doesn't.

You're right; it doesn't. Your code passes char (*)[512].

warning: passing argument 1 of 'snprintf' from incompatible pointer type
/usr/include/stdio.h:385: note: expected 'char * __restrict__' but
argument is of type 'char (*)[512]'

> And so you misunderstand the difference between a C array and a
> pointer.

You make a pretty big assumption.

Given "char buf[512]", buf's type is char * according to the compiler
and every C textbook I know of. With a static char array, there's no
need to take it's address since it *is* the address of the first
element. Taking the address can lead to problems if you ever substitute
a dynamically-allocated buffer for the statically-allocated one. For
one-dimensional arrays at least, static arrays and pointers are
interchangeable when calling snprinf. You do not agree?

Anyway, this is far enough away from Python.
From: Jorgen Grahn on
On Wed, 2010-06-30, Michael Torrie wrote:
> On 06/30/2010 03:00 AM, Jorgen Grahn wrote:
>> On Wed, 2010-06-30, Michael Torrie wrote:
>>> On 06/29/2010 10:17 PM, Michael Torrie wrote:
>>>> On 06/29/2010 10:05 PM, Michael Torrie wrote:
>>>>> #include <stdio.h>
>>>>>
>>>>> int main(int argc, char ** argv)
>>>>> {
>>>>> char *buf = malloc(512 * sizeof(char));
>>>>> const int a = 2, b = 3;
>>>>> snprintf(&buf, sizeof buf, "%d + %d = %d\n", a, b, a + b);
>>>> ^^^^^^^^^^
>>>> Make that 512*sizeof(buf)
>>>
>>> Sigh. Try again. How about "512 * sizeof(char)" ? Still doesn't make
>>> a different. The code still crashes because the &buf is incorrect.
>>
>> I haven't tried to understand the rest ... but never write
>> 'sizeof(char)' unless you might change the type later. 'sizeof(char)'
>> is by definition 1 -- even on odd-ball architectures where a char is
>> e.g. 16 bits.
>
> You're right. I normally don't use sizeof(char). This is obviously a
> contrived example; I just wanted to make the example such that there's
> no way the original poster could argue that the crash is caused by
> something other than &buf.
>
> Then again, it's always a bad idea in C to make assumptions about
> anything.

There are some things you cannot assume, others which few fellow
programmers can care to memorize, and others which you often can get
away with (like assuming an int is more than 16 bits, when your code
is tied to a modern Unix anyway).

But sizeof(char) is always 1.

> If you're on Windows and want to use the unicode versions of
> everything, you'd need to do sizeof(). So using it here would remind
> you that when you move to the 16-bit Microsoft unicode versions of
> snprintf need to change the sizeof(char) lines as well to sizeof(wchar_t).

Yes -- see "unless you might change the type later" above.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
From: Nobody on
On Wed, 30 Jun 2010 23:40:06 -0600, Michael Torrie wrote:

> Given "char buf[512]", buf's type is char * according to the compiler
> and every C textbook I know of.

No, the type of "buf" is "char [512]", i.e. "array of 512 chars". If you
use "buf" as an rvalue (rather than an lvalue), it will be implicitly
converted to char*.

If you take its address, you'll get a "pointer to array of 512 chars",
i.e. a pointer to the array rather than to the first element. Converting
this to a char* will yield a pointer to the first element.

If buf was declared "char *buf", then taking its address will yield a
char**, and converting this to a char* will produce a pointer to the first
byte of the pointer, which is unlikely to be useful.