|
I'm working through learning C with the Dennis* Ritchie & Brian Kernighan book. Spent more time fiddling with the environment than programming the last few days however... I am on excersize 1.9. Been able to figure them out so far. I found a site with all the exercises as the books, in the same order. So I started going there afterwards to check how my solutions fare against the ones there. This is how I approached the excersize of removing all double or longer blanks, and it works when I test it on a text file I got set up. The site solution seems to be doing what I came up with though I think my syntax is more compact. https://www.learntosolveit.com/cprogramming/ex_1.9_sinblank I note they set up an initial value for the previous char as well as used a symbolic constant. I didn't do any of that since I didn't see the point. But is this a practice I should consider when doing C? Just trying to get good habits in from the start. *I share the same name as the creator of C, that bodes well His Divine Shadow fucked around with this message at 18:44 on Jan 1, 2023 |
# ? Jan 1, 2023 18:42 |
|
|
# ? Jun 7, 2024 07:12 |
|
Pretty sure not initializing pc means that the program is permitted to make your computer explode, or at least delete all your files and send nasty e-mails to all people you care about. (The value can be accessed while not initialized if the first character is a space; the term is "undefined behavior"). OddObserver fucked around with this message at 18:54 on Jan 1, 2023 |
# ? Jan 1, 2023 18:49 |
|
Edit: quote is not edit, my apologies
|
# ? Jan 1, 2023 18:53 |
|
Pro tip: if you have a variable named "pc" that needs a comment to explain it means "previous character", just name it previous_character instead. Variable names are comments too. That's not the style in the K&R book but we don't program on 80 character wide mainframe terminals anymore. And yeah if the first character is ' ' you read from pc without setting its value which is undefined behavior. In most cases means you get whatever random garbage data was already sitting in that spot in memory. RPATDO_LAMD fucked around with this message at 19:02 on Jan 1, 2023 |
# ? Jan 1, 2023 18:59 |
|
Thanks that makes sense, learned the importance of initializing variables.
|
# ? Jan 1, 2023 19:12 |
|
More descriptive variable names and initializing values are important. Couple of other small things that matter for larger, longer lived programs: - You should indent the putchar line since it follows the if statement. The indents make the execution flow easier to read, and it is just a universal standard. I prefer to also always have braces, even for one line if statements, because it makes the code clearer and easier to expand. - c and pc are ints, seems like they should be char, I assume that's the type that get_char returns.
|
# ? Jan 1, 2023 19:28 |
|
The book used ints in the examples and said this is because in a single character inside '' quotes is actually a small integer so it works with ints Apparently you can use char, but chars don't like negative values, which might be returned by some non-ascii characters. So not a problem with ints, but apparently you can use a signed char to make it allow negative values. Or use ints? My understanding might be flawed.
|
# ? Jan 1, 2023 19:49 |
|
Learning C from K&R in the year 2023 seems really counterproductive unless your goal is explicitly to learn how C was written forty years ago. The modern C standard has more expressive power and safety than K&R had at the time. That said I’ve been in C++ for long enough that I don’t know any modern resources for learning modern C, so. Maybe someone else here does?
|
# ? Jan 1, 2023 19:53 |
|
StumblyWumbly posted:- c and pc are ints, seems like they should be char, I assume that's the type that get_char returns. No, they have to be ints, because they must be able to hold the value EOF which is outside the range of type char.
|
# ? Jan 1, 2023 19:55 |
|
csammis posted:Learning C from K&R in the year 2023 seems really counterproductive unless your goal is explicitly to learn how C was written forty years ago. The modern C standard has more expressive power and safety than K&R had at the time. I like this way personally. It's more interesting I find. And I asked around the net before starting, asking about books and so, this was still recommended by loads of people to me. This is the 2nd edition which uses ANSI C which is very close to modern C that it should not be an issue.
|
# ? Jan 1, 2023 20:00 |
|
I'm learning it through Algorithms in C and I'm enjoying it a lot.
|
# ? Jan 1, 2023 20:15 |
|
If you’re going to stick with K&R you can still crank up the warnings offered by your compiler. Reading known uninitialized variables would be a compilation error in the codebase at my job. Sometimes they can get annoying to deal with, but a little poking into why something’s considered a warning/error can be a real learning experience.
|
# ? Jan 1, 2023 22:05 |
|
csammis posted:That said I’ve been in C++ for long enough that I don’t know any modern resources for learning modern C, so. Maybe someone else here does? Here's a book that's literally called Modern C . It has some questionable advice that I disagree with from place to place and the style reeks of being academic, but I still think it should be better than K&R. Edit: It looks like the author has a free version of this book here. Beej's Guide to C Programming looks to be updated regularly. I haven't read through it but based on the table of contents, it seems to cover all the modern features. qsvui fucked around with this message at 23:58 on Jan 1, 2023 |
# ? Jan 1, 2023 23:49 |
|
Agreeing with folks ITT that K&R is a book that everyone recommends but nobody actually reads and whose value is pretty marginal these days - I consider C99 an absolute minimum in terms of language revisions, and as others have said make sure you've enabled compiler warnings with -Wall or potentially -Wextra so the compiler can let you know when you're doing something potentially wrong. Can confirm that Beej's book is good; I used it when I taught sophomores their intro to C class. His Divine Shadow posted:Apparently you can use char, but chars don't like negative values, which might be returned by some non-ascii characters. So not a problem with ints, but apparently you can use a signed char to make it allow negative values. Or use ints?
|
# ? Jan 2, 2023 04:25 |
|
Dijkstracula posted:This is sort of correct - whether chars "like negative values" refers to its signedness, and this is actually compiler-specific since the C standard doesn't specify anything about chars beyond "they're one byte in size". It's just "the smallest integer type, as large as the smallest adressable memory thing". Good and honest systems translate this to "one byte at 8 bits", but there were some weirdos out there with 6bit-chars.
|
# ? Jan 2, 2023 12:39 |
|
Wipfmetz posted:I might confuse C and C++ here, but I think the standard doesn't even say that @ one byte. The data type is sizing though. And an unsigned or signed modifier affect signedness. With a signed default. I don't remember if representation of signedness as two's complement is specified in the standard; I'd guess it's implementation defined for those weird 70s machines that have a hardware sign bit.
|
# ? Jan 2, 2023 15:44 |
No, two's complement is specifically not in the C standard. That's (part of?) why signed integer overflow is undefined behavior.
|
|
# ? Jan 2, 2023 16:00 |
|
In fact, C++ only started requiring two’s complement for signed numbers in C++20
|
# ? Jan 2, 2023 16:04 |
|
Wipfmetz posted:I might confuse C and C++ here, but I think the standard doesn't even say that @ one byte. One byte is not 8 bits, it's "as large as the smallest addressable memory thing".
|
# ? Jan 2, 2023 17:14 |
|
Wipfmetz posted:I might confuse C and C++ here, but I think the standard doesn't even say that @ one byte. Dijkstracula fucked around with this message at 19:00 on Jan 2, 2023 |
# ? Jan 2, 2023 18:53 |
|
Wipfmetz posted:I might confuse C and C++ here, but I think the standard doesn't even say that @ one byte. There are/were architectures out there with 5, 6, or 9-bit bytes! C was designed to work on a variety of architectures back when poo poo was way less standardized/interoperable RPATDO_LAMD fucked around with this message at 20:04 on Jan 2, 2023 |
# ? Jan 2, 2023 20:00 |
|
more falafel please posted:One byte is not 8 bits, it's "as large as the smallest addressable memory thing".
|
# ? Jan 2, 2023 20:01 |
|
RPATDO_LAMD posted:There are/were architectures out there with 5, 6, or 9-bit bytes! C was designed to work on a variety of architectures back when poo poo was way less standardized/interoperable The more common case (still can be encountered) are implementations that have their "byte" as 16-bit or 32-bit. I never worked with such an implementation directly, but when I was in robotics not that long ago people had worked with such implementations, as well as signed magnitude implementations.
|
# ? Jan 2, 2023 23:04 |
|
nielsm posted:That's (part of?) why signed integer overflow is undefined behavior.
|
# ? Jan 3, 2023 06:25 |
|
Foxfire_ posted:The main reason I think it's still around is that an optimizer being able to assume that things like "x+1 is always greater than x" is useful Why would this differ between signed and unsigned integers?
|
# ? Jan 3, 2023 09:36 |
|
mmkay posted:Why would this differ between signed and unsigned integers? Because unsigned integers acting modulo 2^(bit size) is also a useful behaviour that some legitimate programs want to intentionally take advantage of.
|
# ? Jan 3, 2023 09:46 |
|
mmkay posted:Why would this differ between signed and unsigned integers? Many decades ago, enough systems handled unsigned overflow identically, but not signed overflow. You also want at least one type that wraps, for easy math use.
|
# ? Jan 3, 2023 09:59 |
|
mmkay posted:Why would this differ between signed and unsigned integers? Because everybody writes for (int i = 0; ...) and nobody writes for (unsigned int i = 0; ...).
|
# ? Jan 3, 2023 20:30 |
|
There's 0 technical need to make signed overflow undefined, it could've just been implementation defined in the same way that sizeof(int) is. Each compiler can do its own thing but they have to be consistent and sensible about whatever thing they chose. Marking it as UB just lets the compiler pretend/assume "this will never happen" and enables a few optimizations as a result. They could've done the same thing with unsigned overflow! But it would break a lot more programs and piss a lot more programmers off since using unsigned overflow for meaningful things is more common in real codebases.
|
# ? Jan 3, 2023 20:34 |
|
pseudorandom name posted:Because everybody writes for (int i = 0; ...) and nobody writes for (unsigned int i = 0; ...). Did the latter. Had a bug. Compiler turned my code into an endless loop. Was schooled on the GCC mailing list on how this was my bug.
|
# ? Jan 3, 2023 21:25 |
|
Once in a while you'll see someone do:code:
Oops.
|
# ? Jan 4, 2023 06:44 |
|
Presto posted:Once in a while you'll see someone do: i had that happen to me last year even though i've been writing embedded c for 10 years.
|
# ? Jan 4, 2023 11:06 |
|
Presto posted:Once in a while you'll see someone do:
|
# ? Jan 4, 2023 13:55 |
|
Even better:C++ code:
|
# ? Jan 4, 2023 16:20 |
|
pseudorandom name posted:Because everybody writes for (int i = 0; ...) and nobody writes for (unsigned int i = 0; ...). I wrote the latter all the time for brevity (with size_t in particular) and to avoid signed-unsigned comparisons, though now of course they’re all range-based fors wherever possible.
|
# ? Jan 4, 2023 16:29 |
|
Sigh, kinda wish they had just made vector sizes a signed int. Who actually needs that last bit of storage afforded by 2^64 vs 2^63? Unsigned arithmetic is important but I feel like it should be totally opt-in, not mandated by the most basic vector api
|
# ? Jan 4, 2023 17:58 |
|
giogadi posted:Sigh, kinda wish they had just made vector sizes a signed int. Who actually needs that last bit of storage afforded by 2^64 vs 2^63? Of all the issues I have with the design of the STL, "doesn't allow negative vector sizes" is not among them tbh
|
# ? Jan 4, 2023 18:07 |
|
It’s not like they’d actually allow negative sizes: the sizes are all controlled by the vector api. But then it would allow completely sane and sensible comparison with signed ints which is what people should be using all the time anyway. “Unsigned int tells people it can’t be negative” is not actually useful when the failure mode ends up being a silent overflow. E: or underflow, loving whatever. giogadi fucked around with this message at 18:13 on Jan 4, 2023 |
# ? Jan 4, 2023 18:11 |
|
Unsigned int should usually mean "raw bit pattern" not "integer value that logically can't be negative". Sometimes even values that can't be negative can be subtracted from and you end up with really stupid bugs when the difference would be negative. Subtracting two vector sizes to get the difference between them? Better make drat sure to check which one's bigger first.
|
# ? Jan 4, 2023 18:22 |
|
|
# ? Jun 7, 2024 07:12 |
|
The C integer promotion rules aren't helping. Did you add two unsigned values? Well if their size was smaller than int's, you now have a signed int, get hosed.
|
# ? Jan 4, 2023 18:59 |