Live data from Hacker News

C Strings and my slow descent to madness

deusinmachina.net

121–130 of 329 posts

Re: C Strings and my slow descent to madness

#121

Earlier quoted context omitted.

There is indeed just convention. The language defines string constants similar to what you say[1] (an array of characters, terminated by a null character), but in the language itself there's no way to declare that a function takes a string rather than a pointer to a character. Alternatively if you work with a fixed-sized character array, there's nothing separating it from "just" an array of characters that are not nu…

That means that the strings aren't properly reflected in the type system. But the existence of string literals with a very definite in-memory layout means that it's not just a convention even so.

But you can't use those string literals in any way without relying on convention.

Re: C Strings and my slow descent to madness

#122
post #83
post #3

It's unfortunate the author put the arrays-are-pointers thing so early in the doc, as that's a very beginner-to-C mixup and really nothing at all to do with strings. Otherwise, yep. It's pretty bad. C is a great language, but its string handling is definitely garbage. You get used to it pretty quick, and it's not hard to write a handful of sane wrappers or a simple string library for your own use, but the standard li…

This is almost a cliche among many C language lawyers and/or Stack Overflow answer-rich people and I know you mean well, but: arrays are not pointers. In some contexts, the name of an array decays to a pointer to its first element. That is a better way of putting it, and it's a (much) weaker statement. Edit: if they were the same, this code: int foo[] = {1, 2, 3}; int *bar = foo; printf("%zu and %zu\n", sizeof foo, s…

This also makes a big difference once we start talking about pointers to arrays.

    int a[] = {1, 2, 3}
    int (*p1)[3] = &a; // ok
    int (*p2)[3] = &a[0]; // not ok
    int *p3 = &a; // not ok
(It should be noted that these will compile with warnings in C due to implicit conversions via void*, but you're still risking UB if you actually use the resulting value. They are all errors in C++ because it doesn't have implicit conversion from void*.)

Re: C Strings and my slow descent to madness

#123
post #33

> Our last function is strcmp. It looks at two strings and determines whether they are equal to each other or not. If they are it returns 0. If they aren’t it returns 1. No it doesn’t. RETURN VALUES The strcmp() and strncmp() functions return an integer greater than, equal to, or less than 0, according as the string s1 is greater than, equal to, or less than the string s2. The comparison is done using unsigned charac…

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...

Re: C Strings and my slow descent to madness

#124

Earlier quoted context omitted.

That means that the strings aren't properly reflected in the type system. But the existence of string literals with a very definite in-memory layout means that it's not just a convention even so.

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!

Re: C Strings and my slow descent to madness

#125

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. It is not that difficult in practice. The old C std lib is, in my opinion, outdated, obsolete and a very bad fit for complex string handling, especially on the memory management side. In my own framework, the string management module is using a dedicated memory allocator and a "high l…

> 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?

Glib answer (but also relevant because mentioned in the article, too): it would look a lot like how a lot of people write C++.

Re: C Strings and my slow descent to madness

#126
> At first this looks great, but there is a problem. What happens when the source string minus the null terminator is as long as the size of the destination string? The answer is that the destination gets filled with all the characters of the source string with no room left for the null terminator.

The 'n' in strncpy is mainly there to help you avoid overrunning the destination, it does not guarantee whatever makes in there is null-terminated.

This is why you should always explicitly set the last byte to zero after using strncpy (and never ever use strcpy).

  char dest[16];

  strncpy(dest, src, 15);
  dest[15]=0;

Re: C Strings and my slow descent to madness

#127

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. It is not that difficult in practice. The old C std lib is, in my opinion, outdated, obsolete and a very bad fit for complex string handling, especially on the memory management side. In my own framework, the string management module is using a dedicated memory allocator and a "high l…

> 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 problem is that it's just too tempting to write something like

    my_function(my_var, 3.6, "bzarflo", my_other_var, false);
The string handling functions are part of the story, but the null-terminated char * is produced when the compiler reaches a string literal, and writing code without being allowed to just use string literals when it's convenient tends to feel like coding with oven mitts on.

Re: C Strings and my slow descent to madness

#128

Earlier 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?

Glib answer (but also relevant because mentioned in the article, too): it would look a lot like how a lot of people write C++.

>Glib answer

A Freudian slip, methinks.

Re: C Strings and my slow descent to madness

#130
post #106

Earlier quoted context omitted.

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…

Linux's strscpy addresses these issues.

Which is great if you're a kernel developer, a bit of a moot point for application developers.
Post reply on HN