|
Jabor posted:My guess would be it's some kind of "sort by A, then B, then C", and they only want to switch the direction of one of those comparisons. Pretty much. A is reversible, but B needs a little more finagling.
|
# ? Mar 9, 2023 15:13 |
|
|
# ? Jun 1, 2024 14:45 |
|
There’s also qsort_r that forwards a context down to the comparator.
|
# ? Mar 9, 2023 15:28 |
|
LLSix posted:Pretty much. A is reversible, but B needs a little more finagling. Just use stablesort and sort step by step.
|
# ? Mar 9, 2023 18:11 |
|
rjmccall posted:There’s also qsort_r that forwards a context down to the comparator. I was going to suggest that but then I got the poster mixed up with the goon still using Borland C or whatever for their course.
|
# ? Mar 10, 2023 02:01 |
|
Has anybody seen and tried some strategies for getting mocks into unit tests for C code? Not C++, but C. I can't really imagine doing it thoroughly without devolving into some kind of macro hell. But who knows, maybe there's some compiler-specific moon beams or something.
|
# ? Mar 13, 2023 15:23 |
|
Fundamentally you just want to link against a mock implementation of your dependency instead of the real implementation, right? I guess it gets complicated if you want your mock implementation to pass through to the real impl under some conditions.
|
# ? Mar 13, 2023 15:32 |
|
You could do an ad-hoc implementation of vtables with function pointers.
|
# ? Mar 13, 2023 15:40 |
|
Rocko Bonaparte posted:Has anybody seen and tried some strategies for getting mocks into unit tests for C code? Not C++, but C. I can't really imagine doing it thoroughly without devolving into some kind of macro hell. But who knows, maybe there's some compiler-specific moon beams or something. for prod: -lprod_version for test: -lmock_version or, we just impl whatever function we need in the test itself if it is small/configuration. #include the header, implement the function, no link needed and mock is embedded right next to test
|
# ? Mar 13, 2023 15:41 |
|
I'll accept some clever linking as a way around macro hell. Although:Jabor posted:I guess it gets complicated if you want your mock implementation to pass through to the real impl under some conditions. Yeah, I have a bunch of legacy code and I'd imagine having to wade through this nightmare if we wanted to start to get some unit testing of any kind. Even trying to old "just add unit tests for the new code" isn't straightforward with a library swap.
|
# ? Mar 13, 2023 16:00 |
|
Rocko Bonaparte posted:I'll accept some clever linking as a way around macro hell. Although: Shave parts of the main application off into libraries. Test the libraries. Not sure why this is sounding more annoying here than in any other language? Is the hangup managing the build rules?
|
# ? Mar 13, 2023 16:55 |
|
Rocko Bonaparte posted:Has anybody seen and tried some strategies for getting mocks into unit tests for C code? Not C++, but C. I can't really imagine doing it thoroughly without devolving into some kind of macro hell. But who knows, maybe there's some compiler-specific moon beams or something. Use the same headers but different definitions in different files. What we do is link in the mock files only in in the unit test compile. e.g. Foo.h foo(int bah); foo.c //real file #include "foo.h" foo(int bah { blah } bar.c //real file #include "foo.h" bar(int z) { foo(z); ... } //make file for product ... foo.c bar.c foo_mock.c //mock for testing #include "foo.h" foo(int bah { different blah } //make file for unit testing ... foo_mock.c bar.c Obviously this only works if you are compiling individual files in your unit test compile and not the entire library. Admittedly, it took me most of a year to feel comfortable enough with the code base to do this, but it seems to be holding for the ~40% of the code base we've got covered now. LLSix fucked around with this message at 19:04 on Mar 13, 2023 |
# ? Mar 13, 2023 17:52 |
|
I have a question about boost ASIO strand: Is a strand an executor or does it just have an executor? That is, if I make a ip::tcp::socket socket{strand} will then the async_receive/async_send be guaranteed to be executed serially? I saw some stackoverflow posts that say it is an executor, but I didn't see anything in the official documentation saying so. My main use case here would be to not make a socket from an io_context but then to have to use bind_executor for the completion handler. The code would be that much simpler if I can just make the socket from the strand directly and then just use async_receive/async_write normally.
|
# ? Mar 13, 2023 18:32 |
|
I don't have a question but I just want to say the bitwise exercise in the C book I got is hard and makes me feel stupid. I had to go look at the solution and looked at alternative solutions and feel like I am barely hanging on. Hopefully I'll get there.
|
# ? Mar 14, 2023 10:23 |
|
His Divine Shadow posted:I don't have a question but I just want to say the bitwise exercise in the C book I got is hard and makes me feel stupid. I had to go look at the solution and looked at alternative solutions and feel like I am barely hanging on. Hopefully I'll get there. for bitwise stuff, I find it helpful to draw literal binary values on paper to model things out. can't juggle that poo poo in my head any more
|
# ? Mar 14, 2023 13:42 |
|
I have a function that writes it out on screen for me actually. Lifesaver. Though there might be some merit to writing on paper.
|
# ? Mar 14, 2023 14:55 |
|
The calculator in KDE (KCalc) has a "Show Bit Edit" mode. It's awesome. It surely must be a feature in other calculators.
|
# ? Mar 14, 2023 15:38 |
|
Windows calculator (at least as of Windows 10) has a "programmer" mode that does a bunch of hex/octal/binary stuff.
|
# ? Mar 14, 2023 17:02 |
|
Curses, beaten.
|
# ? Mar 14, 2023 17:02 |
|
When I'm doing bit stuff, I usually just think of it as an array of bools that you notate in a weird way, and will write out any constant I'm |ing or &ing with in 0b binary notation to emphasize which bits I'm using and make it more closely resemble logical operators than math operators.
|
# ? Mar 14, 2023 19:40 |
|
cheetah7071 posted:When I'm doing bit stuff, I usually just think of it as an array of bools that you notate in a weird way, and will write out any constant I'm |ing or &ing with in 0b binary notation to emphasize which bits I'm using and make it more closely resemble logical operators than math operators. Yeah, I've been doing bit-twiddling in some capacity off and on for 20+ years and I can't "see" the bits when a constant is written in hex (or worse, octal) still. 0b is great.
|
# ? Mar 14, 2023 19:48 |
|
Maybe I'm missing something, but why do you need to see anything? Suppose you have a definition like this:code:
dWord reserved
|
# ? Mar 14, 2023 21:00 |
|
Let's say I have a pile of C kernel modules using the old init_module style that need to be changed to rename that to [insert_module_name_here]_init_module and then add module_init([insert_module_name_here]_init_module) in the same file. Is there some C refactoring tool where I could set that up for a hundred or so operations? I was figuring there must be something better than, say, bringing up ANTLR4 and writing a custom visitor or something. Just casually Googling was pretty disappointing, but it just might be that C++ is taking over that conversation that's a far harder language to reliably munge.leper khan posted:Shave parts of the main application off into libraries. Test the libraries. A lot of it is it's kernel level code hitting a lot of special functions that we'd have to somehow mock. So presumably we'd be replacing all those calls and kernel boilerplate with a localized equivalent in a different, userspace library. I've been generally just trying to keep as much logic out of kernel-specific stuff. It's ... okayish for new code but it's not something I can readily do for a pile of legacy code unless I can do that initial refactor . . . without having any unit test coverage to prove I did it correctly. The big reason I've been pretty pumped about Rust getting into the kernel is I think it would give me places where I can more easily switch out for mocks for testing kernel-level code.
|
# ? Mar 14, 2023 21:15 |
|
ultrafilter posted:Maybe I'm missing something, but why do you need to see anything? Suppose you have a definition like this: I do basically this but it's just C++ code:
C++ code:
|
# ? Mar 14, 2023 21:36 |
|
Rocko Bonaparte posted:Let's say I have a pile of C kernel modules using the old init_module style that need to be changed to rename that to [insert_module_name_here]_init_module and then add module_init([insert_module_name_here]_init_module) in the same file. Is there some C refactoring tool where I could set that up for a hundred or so operations? I was figuring there must be something better than, say, bringing up ANTLR4 and writing a custom visitor or something. Just casually Googling was pretty disappointing, but it just might be that C++ is taking over that conversation that's a far harder language to reliably munge. For that sort of refactor I usually just rely on vim's bufdo and then review the output diff. For testing the code, you just build it with a test harness that calls it and evaluates results.
|
# ? Mar 14, 2023 21:49 |
|
cheetah7071 posted:I could have called it 127 or 0x7F but 0b01111111 just makes it more clear to me at least what I'm actually doing here, to me. Exactly, I know intellectually that 127 and 7f are that same bit pattern, but I have to actually go through the step of Thinking About It, and my brain is terrible with things like off-by-ones (mostly, whether I should be correcting for an off-by-one or not). Any time I have to Think About It I increase the chance that I'll do it wrong. 0b01111111 makes it very clear that every bit except the MSB is set, so in the context of a mask, I can immediately see that that mask will give the same input with the MSB cleared.
|
# ? Mar 14, 2023 21:58 |
|
cheetah7071 posted:Like I have a file format where one of the bytes has 7 bits that represent a number from 0 to 127, and one bit which represents whether the data that follows is compressed or not. So my code for accessing the numeric portion is: I'd write that as follows: C++ code:
|
# ? Mar 14, 2023 22:04 |
|
For flags I use enums (none of this 0x01, 0x02 stuff, just a normal enum class) along with a Flags<T> class which wraps a uint and provides a nice interface for flagsy operations. I prefer x[flag] = false; over x &= ~flag, but either style works. I've not run into any downsides with it yet except that it doesn't benefit from any built-in debugger flags visualisation.
|
# ? Mar 14, 2023 22:11 |
|
ultrafilter posted:I'd write that as follows: Clearly. I think you'd want a tilde there.
|
# ? Mar 14, 2023 22:34 |
|
Would've been caught in tests.
|
# ? Mar 14, 2023 23:06 |
|
Rottbott posted:For flags I use enums (none of this 0x01, 0x02 stuff, just a normal enum class) along with a Flags<T> class which wraps a uint and provides a nice interface for flagsy operations. I prefer x[flag] = false; over x &= ~flag, but either style works. I've not run into any downsides with it yet except that it doesn't benefit from any built-in debugger flags visualisation.
|
# ? Mar 15, 2023 00:49 |
|
Well here's how I attempted to do exercise 2-7 in my C book. I have not looked at the answer yet but I feel pretty sure it's radically different, more compact. I do believe this code is pretty inefficient and can be optimized a lot and most of the x* variables can be removed but I wrote out it out like this to make it simpler to see and understand what's happening. The exercise is that I want to flip or invert any bits, starting at position p as well as n bits to the left of p. Leaving the rest unchanged. My idea was to make two bit masks to mask of the area that is to be flipped, combine that into a new mask and then use said mask with a XOR operator on the original. I've tested it on a couple of numbers and it seems to work. I noticed I have to use p-1 to start from bit 4 and not 5, which OK I can see that might work, it counts from 1 not 0 I guess. But then (p-1)+n doesn't yield the correct offset. There I have to remove the -1 . I'm still not sure why and I don't like it.
|
# ? Mar 15, 2023 06:24 |
|
His Divine Shadow posted:Well here's how I attempted to do exercise 2-7 in my C book. I have not looked at the answer yet but I feel pretty sure it's radically different, more compact. I do believe this code is pretty inefficient and can be optimized a lot and most of the x* variables can be removed but I wrote out it out like this to make it simpler to see and understand what's happening. The exercise is that I want to flip or invert any bits, starting at position p as well as n bits to the left of p. Leaving the rest unchanged. I would do something like code:
Though there's likely something a bit more efficient in the bit twiddling hacks document.
|
# ? Mar 15, 2023 06:40 |
|
roomforthetuna posted:Another downside is it's pretty hostile to any sort of serialization that treats the bytes-with-flags-in as bytes or ints or whatever, like old structs or various file formats. True, if you were wanting to just cast some bytes into Flags<T>, but it's easy to convert to/from the underlying int if you need it. I've my own serialisation system so Flags presents itself to that as just an int. It's like any class which wraps a simple value to give it a nice interface, really. Say, a units library or a date-time class. Nobody would blink at using those so I don't know why more people don't do this with flags. It's really nice to use.
|
# ? Mar 15, 2023 08:23 |
|
ultrafilter posted:Maybe I'm missing something, but why do you need to see anything? Suppose you have a definition like this: I agree that if all you're doing is setting and checking individual independent bits in a bitfield it's not really a problem, but that's the simplest application of bit twiddling. If you're doing something more involved then visualizing the bits can definitely be helpful. E.g. when dealing with custom serialization code or network serialization, custom numeric representations (like fixed-point) or other tricky low-level math stuff, that sort of thing.
|
# ? Mar 15, 2023 09:22 |
|
leper khan posted:I would do something like Is there an advantage to doing it that way? code:
|
# ? Mar 15, 2023 19:16 |
|
readability?
|
# ? Mar 15, 2023 19:18 |
|
His Divine Shadow posted:Is there an advantage to doing it that way? Fewer arithmetics. Readability. Real answer requires perf testing I'm too lazy to do right now for you
|
# ? Mar 15, 2023 23:37 |
|
leper khan posted:Fewer arithmetics. Readability. Real answer requires perf testing I'm too lazy to do right now for you
|
# ? Mar 16, 2023 00:46 |
|
His Divine Shadow posted:Is there an advantage to doing it that way? If they do compile to anything different, I'd guess it'd be from them doing different undefined behavior things on some inputs. A bunch of bitshift operations are undefined or implementation defined when applied to signed values when the shift amount is negative or bigger than the type being shifted. Reminds me of a college assignment where we had a bunch of different functions to implement ("mirror this bit pattern" like you have, "count the number of set bits", ...) with per-function restricted sets of permitted operations and graded based on how many operations you used. Nothing you'd ever do in real code, but a reasonably entertaining way to teach bitwise stuff and edge case behavior.
|
# ? Mar 16, 2023 03:13 |
|
|
# ? Jun 1, 2024 14:45 |
|
roomforthetuna posted:Almost guarantee that with optimizations on they will compile to the same thing. For modern compilers I wouldn't be surprised if that was true.
|
# ? Mar 16, 2023 03:57 |