Live data from Hacker News

C Strings and my slow descent to madness

deusinmachina.net

71–80 of 329 posts

Re: C Strings and my slow descent to madness

#71

It's important to mention that strncpy (and also strncpy_s) are really not a strcpy replacement, it's not intended for the same usages. The name is a total misnomer. Do not use strncpy that way! In any case, strcpy_s (which is a good replacement for strcpy) is part of the C11 standard. I'm confused how that isn't considered portable.

it's an _optional_ part of the standard, and so can't be relied on. also, the idea behind it is pretty poor.

Re: C Strings and my slow descent to madness

#72
post #27

I don't use null terminated strings. ptr+len struct everywhere. And when I need to call an API, like fopen, I make a temporary copy of that string + the null termination, do my work and then free it. You can printf non-null terminated strings too. Check printf("%.*s", length, strptr).

A long time ago my solution was ptr+len but I allocated 1 more byte so that if a string had to be given to libc, I could terminate it at that time. No need for a copy then.

Re: C Strings and my slow descent to madness

#73
post #6

Yes this is something to get use to. The BSDs created strlcpy(3) and wcslcpy(3) https://man.openbsd.org/strlcpy.3 https://man.openbsd.org/wcslcpy.3 which to me will help with some of these issues. Too bad other Operating Systems do not have these. On Linux there is libbsd to get these, but I would like to see these to be added to the stdc. Instead the c23 standard is messing with realloc(3) which could break some old…

strlcpy is nice due to the guaranteed NUL termination. strlcpy is not so nice due to the strange (IMO) return value of the number of characters in the source string . Which could be the number of characters copied or much, much larger than the number of characters copied. snprintf does the same thing. So using strlcpy is safe (by C's low bar) but using the return value may be highly unsafe.

The thing that annoys me the most about strlcpy is that it is supposed to be safer, but what happens in the case where the source string is not properly NULL terminated? You might think that it will stop at the character limit you specified, but that's not what it does. It just blows on past the end of the buffer looking for a \0 until it either finds one or causes a segmentation violation.

IMHO I would like it much more if the return values were:

  0: string copied
  1: string partially copied but truncated
  -1: Error, errno set.  This can occur when src or dst are NULL.

Re: C Strings and my slow descent to madness

#74
post #8

I've been wondering lately why many people write c in c++ rather than just c. I think this might be the reason.

the usual accusation is that many people write c++ code as if it were c. also, the the code in 2nd ed of K&R was all compiled with stroustrup's c++ compiler, as there wasn't a c compiler that could handle it.

Re: C Strings and my slow descent to madness

#75

> If we try to print out some Japanese characters… [] The output isn’t what we expect. Yes it is. And I bet on a modern windows version it is too. The terminal has been (probably intentionally) neglected by ms for a long time, but as far as I know this has mostly been fixed on modern windows versions. EDIT: Author admits it later in the text "will be fixed in Windows 11 and Windows Server 2022" Also it says "strlen("…

> And I bet on a modern windows version it is too. It's still broken unfortunately, you need to switch the console to a special UTF-8 codepage in your own code: SetConsoleOutputCP(CP_UTF8); ...and before exit restore it to the original code page.

... except that that is also subtly broken.

It works if you write multiple UTF-8 code-units in one go, but breaks if you send them in several writes (and by that, I mean direct writes to the HANDLE). It also breaks if you try to use the ANSI API (with the A suffix), as it internally tries to convert the bytes from codepage-random to UTF-8.

You run into both issues if you try to use the MS implementation of stdio (printf and friends).

And we didn't even discuss command line argument passing yet :-)

I had a lot of fun with this (more explanation in the issue comments): https://github.com/AgentD/squashfs-tools-ng/issues/96#issuec...

I tried to test it with the only other two languages I know besides English: German and Mandarin. Specifically also, because the later requires multi-byte characters to work. Getting Chinese text I/O to work at all in a Windows DOS box, on an existing, German Windows 7 installation was an adventure on it's own and ended up breaking things in different ways than German text.

Turns out, trying to write language agnostic command line applications on Windows is a PITA.

Re: C Strings and my slow descent to madness

#76

Earlier quoted context omitted.

> And I bet on a modern windows version it is too. It's still broken unfortunately, you need to switch the console to a special UTF-8 codepage in your own code: SetConsoleOutputCP(CP_UTF8); ...and before exit restore it to the original code page.

... except that that is also subtly broken. It works if you write multiple UTF-8 code-units in one go, but breaks if you send them in several writes (and by that, I mean direct writes to the HANDLE). It also breaks if you try to use the ANSI API (with the A suffix), as it internally tries to convert the bytes from codepage-random to UTF-8. You run into both issues if you try to use the MS implementation of stdio (pri…

Windows is truly the gift that keeps on giving :D

Re: C Strings and my slow descent to madness

#77
post #15
post #8

I've been wondering lately why many people write c in c++ rather than just c. I think this might be the reason.

People write C in C++ because they don't actually know C++ and think it's "basically C with classes and strings". There are legitimate reasons why someone would rather write C, but "I don't understand RAII" is not one of them.

C++ doesn’t require you to commit to all of its features and/or paradigms. Using it as you see fit is valid. Just don’t advertise yourself as a C++ programmer to the job market, as it’s not what most people expect.

There’s nothing wrong with “C with classes and strings” idea by itself, if that is your choice or a consciously sufficient level of competence.

Re: C Strings and my slow descent to madness

#78
post #77
post #15

Earlier quoted context omitted.

People write C in C++ because they don't actually know C++ and think it's "basically C with classes and strings". There are legitimate reasons why someone would rather write C, but "I don't understand RAII" is not one of them.

C++ doesn’t require you to commit to all of its features and/or paradigms. Using it as you see fit is valid. Just don’t advertise yourself as a C++ programmer to the job market, as it’s not what most people expect. There’s nothing wrong with “C with classes and strings” idea by itself, if that is your choice or a consciously sufficient level of competence.

It doesn't require you to commit to all of its features, that's certainly correct. But it does require you to commit to its principles; if you're needlessly passing naked pointers around, you're really writing C code with a C++ compiler.

Re: C Strings and my slow descent to madness

#79
post #71

It's important to mention that strncpy (and also strncpy_s) are really not a strcpy replacement, it's not intended for the same usages. The name is a total misnomer. Do not use strncpy that way! In any case, strcpy_s (which is a good replacement for strcpy) is part of the C11 standard. I'm confused how that isn't considered portable.

it's an _optional_ part of the standard, and so can't be relied on. also, the idea behind it is pretty poor.

Don't GCC, Clang and MSVC provide it? It may be optional in practice but if the major compilers support it, it's not really an issue.

The idea may not be perfect, but for C which is intended to be low overhead, strcpy_s is about as good as it gets. If you want something more user friendly, that is what C++ is for with std::string, or library implementations like Boost or QT string.

Re: C Strings and my slow descent to madness

#80
post #72
post #27

I don't use null terminated strings. ptr+len struct everywhere. And when I need to call an API, like fopen, I make a temporary copy of that string + the null termination, do my work and then free it. You can printf non-null terminated strings too. Check printf("%.*s", length, strptr).

A long time ago my solution was ptr+len but I allocated 1 more byte so that if a string had to be given to libc, I could terminate it at that time. No need for a copy then.

BASIC strings in Windows -- you store the length in the 4 bytes before the pointer to the string and put a null terminator at the end.

https://learn.microsoft.com/en-us/previous-versions/windows/...

Post reply on HN