4 ms·
Ok, sure. But I doubt that's a good practice. In fact, I can't possibly imagine it not being a horrible idea. So, I ask: what size and signedness of int? 1, 2,
by MrMcCall 2y ago
Ok, sure. But I doubt that's a good practice. In fact, I can't possibly imagine it not being a horrible idea.
So, I ask: what size and signedness of int? 1, 2, 4, 8? What if the string is of length 3, 2, 1, 0?
Why bother with all those corner cases. Everything has a memory layout and appropriate semantics of representation and modification. Pushing those definitions is a recipe for problems.
I like to keep it simple, keeping the semantics simple in how I code specific kinds of transforms.
The less kinds of techniques you use, the less kinds of patterns you have to develop, test, and ensure consistent application of across a codebase.
Especially down in C land, which is effectively assembler.
Gone are the days of Carmac having to save bytes in Doom, unless you're doing embedded work, in which case that's all the more reason to be very careful how you handle those bytes.
- SAI_Peregrinus 2y ago> But I doubt that's a good practice That's entirely how "string" indexing works in C. Strings in C are just pointers to `char` with some valid allocation size. As long as the integer used for the pointer offset results in a pointer into the allocation after the addition, it's valid to dereference the result. Remember, `array[index]` is syntactic sugar for `(array + index)` in C. Lots of the C stdlib string functions use this, e.g. `char strchr(const char* str, int character)` has a naive implementation as a simple loop comparing `char`s[1]. Glibc does it one `unsigned long int` at a time, as an optimization, with some extra work at the start going one `char` at a time to ensure alignment. > So, I ask: what size and signedness of int? 1, 2, 4, 8? Doesn't matter, as long as the result of the addition points to within the pointer's allocation. Otherwise you get UB as usual. > What if the string is of length 3, 2, 1, 0? Doesn't matter, as long as the result of the addition points to within the pointer's allocation. Otherwise you get UB as usual. For a 0-length string (pointer to '\0\'), the only valid value to add is 0. > The less kinds of techniques you use, the less kinds of patterns you have to develop, test, and ensure consistent application of across a codebase. 100% agreed. The less C you use for string handling the better. C strings are fundamentally fragile. [1] https://godbolt.org/z/4T835cdKb https://godbolt.org/z/4T835cdKb
- MrMcCall 2y ago> Doesn't matter Any time the microprocessor accesses memory for use as an int, it's a specific kind of int, meaning size and signedness, and the flags are adjusted properly as per the operation performed. > Strings in C are just pointers to `char` with I'm gonna end this here. I taught myself C programming by reading K&R in the late 80s, and then proceeded to do so professionally for YEARS and YEARS. There are people that know, and there are people that act like they know. You ever read the first two chapters of Windows Internals? You ever write C code that could make Windows system calls from the same program that could be 32- or 64-bit with a simple compiler flag? I have. > C strings are fundamentally fragile. Not if you know what you're doing. You're almost certainly using a C program to type this response in an operating system largely written in C. You get any segfaults lately? I don't EVER on either my Ubuntu or Debian systems. Thanks for playing.
- SAI_Peregrinus 2y ago> > Doesn't matter > Any time the microprocessor accesses memory for use as an int, it's a specific kind of int, meaning size and signedness, and the flags are adjusted properly as per the operation performed. Sure. But the C standard specifies how addition of a pointer to an integer works in section 6.5.7, particularly paragraph 9. The specifics of what flags get set & the width of integer used are up to the implementation & the programmer, but > For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a complete object type and the other shall have integer type. (Incrementing is equivalent to adding 1.) should be a pretty clear statement that pointer + integer is valid! > > Strings in C are just pointers to `char` with > I'm gonna end this here. I taught myself C programming by reading K&R in the late 80s, and then proceeded to do so professionally for YEARS and YEARS. > There are people that know, and there are people that act like they know. You ever read the first two chapters of Windows Internals? You ever write C code that could make Windows system calls from the same program that could be 32- or 64-bit with a simple compiler flag? > I have. I'm an embedded C developer. I've been writing C for decades, but not for windows. But I do write code that can work on both 8-bit and 32-bit systems with just a compiler flag. Strings are arrays of character type with a null terminator, and array-to-pointer decay works as usual with them. >> C strings are fundamentally fragile. > Not if you know what you're doing. You're almost certainly using a C program to type this response in an operating system largely written in C. You get any segfaults lately? I don't EVER on either my Ubuntu or Debian systems. > Thanks for playing. C strings are arrays of character type with a null terminator. That is fundamentally fragile, since it includes no information about the encoding or length of the string, and thus allows invalid states to be represented. That doesn't mean you will get segfaults, only that it's possible for someone to screw up & interpret your UTF-8 data as ASCII or write a `\0` in the middle of a string or other such mistake, and you'll get no protection from the type system.