I once got called in to fix an SS7 stack suffering from poor performance. Pretty well written, and not obvious at first sight why it was going slow. Most of it was low-level bit fiddling, and some small strncpy's() - generally about 8 chars or so. Didn't take that long to profile (well, printf's as no profiling available) and figure out it was the strncpy's causing the problem, but why? Well, there was a handy 8 mega…
The appearance of strncpy() in any source code is an immediate panic attack for me. It should never be used, and if it is used, it should be removed. Similar rule for sprintf(), all instances of which should be replaced by snprintf().
C Strings and my slow descent to madness
151–160 of 329 posts
Re: C Strings and my slow descent to madness
#152Earlier quoted context omitted.
I think this naming style should be considered obsolete. - This function will return the number of bytes, not of characters or codepoints. - str and len are both abbreviations, we should use full words when possible - We can also be more explicit about what the function does, it does not simply returns the string length, it counts characters (or bytes in this case) Here is how I would name it: u32 CountBytesInString(…
"- str and len are both abbreviations, we should use full words when possible -" u32 and char are abbreviations.
strlen is also pretty unambiguous, but I still have to check what strstr means.
Re: C Strings and my slow descent to madness
#153`strlcpy` is the function you probably want. but again it is not standard. https://lwn.net/Articles/507319/ I think the reason people don't want to standardise this kind of function is it often gives wrong behaviour. for example if you are trying to copy a string into a fixed buffer and its too long then often it is an error or potentially even a security bug to truncate it. so these functions generally do the 'wrong…
I end up working on a lot of code that uses Glib, so I tend to use g_strdup_printf() a lot, which works the same as asprintf().
Ultimately the cost of allocations is usually not a big deal, and you gain a lot of safety. Sure, you then have to remember to free(), but I'll take a memory leak over a segfault (and its possible security consequences) any day.
And if allocation cost is a problem, you can always go back and optimize with static buffers later. That shouldn't be the default that people reach for, though.
Re: C Strings and my slow descent to madness
#154Earlier quoted context omitted.
But you can't use those string literals in any way without relying on convention.
That was my point. Although you can, actually - since literals themselves are array-typed, you can sizeof them to get the character count without relying on null termination. It's even possible to get a non-null-terminated literal if the target array type is not large enough to fit null, e.g.: char s[3] = "foo"; // not null-terminated!
Byte count.
Re: C Strings and my slow descent to madness
#155Earlier quoted context omitted.
I don't have MacOs to prove it but I believe `strcmp` on MacOs returns either 0, 1 or -1
https://developer.apple.com/library/archive/documentation/Sy...
int d = a[i] - b[i];
if (d == 0) return d;Re: C Strings and my slow descent to madness
#156Earlier quoted context omitted.
"If you are using C and do some non-trivial work with strings you should either use a good library to handle strings or build your own." unsigned int str_len(const char *s) { register const char *t; t = s; for (;;) { if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; } } I still use this instead of stdlib strlen. Of course I also use software everyday that…
Out of curiosity, why do you use this? I expect the builtin strlen() to be even more optimized than this. There's a lot more you can do than a simple loop unrolling.
Re: C Strings and my slow descent to madness
#157Earlier quoted context omitted.
> by default , C strings are bad. C strings aren't bad. They can't be, because they don't exist. C doesn't have strings. And that is the issue. As you say, things get a lot better when you actually introduce strings as a concrete concept rather than a set of lose conventions.
I don't think it's useful to pretend C doesn't have strings when it has string literals. WUFFS doesn't have strings. That's what a language which doesn't have strings looks like, you can't write "Hello, world" in WUFFS because it involves Strings, which WUFFS doesn't have, and I/O, which WUFFS also doesn't have. A pretence that C doesn't have strings because it lacks a concrete string type in the language itself also…
Zig and Rust I don't know enough about.
And I'm not pretending. C has string literals which are of a non-distinct type. You can't distinguish between a string literal and an array of characters. This is the crucial bit.
The result is that the standard library, and lots of other code, relies on convention alone to pass strings around. This has been and continues to be the source for countless serious bugs. The kind of bugs which are a total non-issue in languages which has strings.
[1]: https://en.cppreference.com/w/cpp/language/user_literal
Re: C Strings and my slow descent to madness
#158Well-written C tends to minimise string usage in general, preferring to convert to another format as soon as possible. Allocating, copying, and passing around strings in large quantities is not a good idea for efficiency, but of course some people coming from other HLLs seem to try to do it anyway, which causes many other problems.
Re: C Strings and my slow descent to madness
#159Earlier quoted context omitted.
> the C std lib is the weakest part of the C language and it should only be used as a fallback. I've been musing for a while now: what would it look like if we were to discard the C library and design a new one, leaving the language itself intact?
The old MacOS (pre-X) did just that. Strings were all "Pascal strings", ie. with the first byte containing the length of the actual string. Building blocks for memory were also very different from stdlib, notably the use of Handles, which were pointers of pointers, so that the OS could move a block of data around to defragment the heap behind your back without breaking the memory addressing.
And the wheels fall off with the first string longer than 255 characters.
Re: C Strings and my slow descent to madness
#160Since the May 2019 update, Windows 10 has supported declaring the code page in a manifest file.
In Visual Studio, you must add "/utf-8" to the compiler command line, this makes it parse the source code as a UTF-8 file, and makes it output UTF-8 string literals.
To make console output work, call the Win32 function "SetConsoleOutputCP(65001);"
To get support for opening files with names that aren't in your system codepage:
* Create a manifest file as shown in https://learn.microsoft.com/en-us/windows/apps/design /globalizing/use-utf8-code-page
* Add this as an "Additional Manifest File" in Visual Studio project settings for the manifest tool
Additionally, there is an undocumented NTDLL function "RtlInitNlsTables" that sets the code page for the process. It is difficult to use without a lot of example code, but some app locale type tools (used to change locale for a process) make use of this function.