|
rjmccall posted:As a language designer, I think the right rule is that expression results should default to not being discardable, and functions should have to opt out of that. Yeah, at my last place we annotated 90+% of all our functions with [[nodiscard]] and we had no problems with it. The rest were mostly void functions rjmccall posted:It seems obvious that you could borrow that same funny wording for the standard library's specifications of e.g. c.empty() and c.size() and get the point across without crossing any novel lines like implying that standard library types have member functions. I don't know why anyone would have a problem with that, but it's the C++ committee, so I'm not surprised that somehow this turned into a major fight. So, right now the specification of bunch of things actually uses discard in the standard, e.g. C++ code:
The result is lot of wasted time in discussion, a paper that suggests removing all existing instances of nodiscard in the standard and lot more wasted time by discussing this new paper in actual meeting. Basically every time I am thinking that maybe I could contribute paper once again, this poo poo happens and I decide that nah, this is not worth it ----------------- e ------------ What a great way to start new page.
|
# ? Aug 3, 2021 11:55 |
|
|
# ? Jun 2, 2024 11:49 |
|
Ranidas posted:snip Is the question how to detect a cycle in graph induced over votes in some election?
|
# ? Aug 3, 2021 11:58 |
|
Xarn posted:Is the question how to detect a cycle in graph induced over votes in some election? Yes, and what I'm doing wrong in my approach to a recursive function to do so. I feel like I have the core of the mechanism right, but can't figure out a way to implement it without return path issues. Of course I could be wrong and maybe I'm not anywhere close!
|
# ? Aug 3, 2021 12:56 |
|
You need to keep around some extra information, specifically already visited nodes. Usually you will keep around simple array where you mark a node as visited when you recurse down, and unmark it when you recurse up. If you are about to recurse down a find out that node is already marked, then you've ran into a cycle.
|
# ? Aug 3, 2021 17:28 |
|
Ahhh good old pointers and references. Now I'm starting to get back into the groove. Suppose you are getting a list of names from some kernel module using a helper function. The result would be an int for number of records, a char* for the buffer (that the caller frees), and char** for all the different names in the buffer (that the caller frees). Ahhh, but you need to pass references to all these so suddenly it's int*, char**, char***. Time for a nap!
|
# ? Aug 6, 2021 19:42 |
|
Volguus posted:I always hated begin and end and typing := (although it's easier and clearer to read). Honestly its a lot easier to follow than curly brackets. And less easy to follow than indentation based block structuring. I think its just a matter of what your comfortable with. I grew up on pascal (and basic, but I chose to forget the 80s. Bad hair. Bad music. Bad language) so it was natural for me, and I found curly brackets intimidating. Until eventually I didn't.
|
# ? Aug 10, 2021 05:34 |
|
My pet theory is that language designers pick syntax that's easy to type on their keyboards - and Wirth is Swiss, which means curly brackets are altGr symbols and a bit annoying to type all the time. Forward slash is shift+7 and asterisk shift+3, which means pascal (* comments *) are not significantly worse than C /* comments */ . Of course, he may well have done all his work on a US keyboard, which would entirely invalidate that theory. E: it does look like the machine he designed along with the Oberon language has a US style layout in the Wikipedia image, at least. Oh well. Computer viking fucked around with this message at 22:35 on Aug 10, 2021 |
# ? Aug 10, 2021 22:30 |
|
Computer viking posted:My pet theory is that language designers pick syntax that's easy to type on their keyboards - and Wirth is Swiss, which means curly brackets are altGr symbols and a bit annoying to type all the time. Forward slash is shift+7 and asterisk shift+3, which means pascal (* comments *) are not significantly worse than C /* comments */ . Its more to do with history. WIrth was one of the people behind Algol, and was behind PL360 so when Pascal came out in 1970, its natural he would go with the prevailing standards of the era and use BEGIN and END. When C came out a couple of years later, Richie and Thomson lifted them from B which came out in 69 but was not really known of outside their own lab. I actually prefer pascal comments. ( ) and * are all next to each other whereas / and * are oposite sides (vertically) of the keyboard on the same hand. A little less finger stretching. duck monster fucked around with this message at 07:32 on Aug 11, 2021 |
# ? Aug 11, 2021 07:29 |
|
I have a very weird situation where I learned C on the old MacOS, where the OS, libraries, docs, and samples were written in Pascal. I probably should have just learned Pascal, but compilers cost money, and I had MetroWerks CodeWarrior already.
|
# ? Aug 11, 2021 15:05 |
|
I'm trying to get at most three decimal places after the period on a float. Everything I find tells me to use std::setprecision() code:
Can I simply limit the number of decimal places? setprecision() seems to be limiting the overall precision.
|
# ? Aug 11, 2021 18:34 |
|
Streams are initialized as defaultfloat, which switches to scientific notation whenever the number of digits exceeds the requested precision. 1000 is four digits, and 4 > 3 . std::setprecision(4) would do what you want. There's a std::fixed manipulator you can use to force fixed output. In that mode precision is the number of decimals, so code:
|
# ? Aug 11, 2021 19:16 |
|
Computer viking posted:My pet theory is that language designers pick syntax that's easy to type on their keyboards - and Wirth is Swiss, which means curly brackets are altGr symbols and a bit annoying to type all the time. Forward slash is shift+7 and asterisk shift+3, which means pascal (* comments *) are not significantly worse than C /* comments */ . Pascal's original comment syntax actually used { curly braces }. The digraphs (* *) were meant to be used on systems that didn't have them. code:
|
# ? Aug 11, 2021 19:24 |
|
Huh, I did not know that.
|
# ? Aug 12, 2021 23:09 |
|
Question about replacing macros, static analysis tools hate (most of) them for good reason, but I'm unsure of what the best replacement is. Define a bunch of static inline functions for all required types, possibly with a macro'd _generic access, or a single templated version? Does it even matter?
|
# ? Aug 13, 2021 06:51 |
|
What kind of macros? What are they doing?
|
# ? Aug 13, 2021 07:19 |
|
Xarn posted:What kind of macros? What are they doing? This. Macros (the language feature) are evil. Macros (the things in your codebase) are probably suspect, but not necessarily a problem. There's lots of situations where macros are, actually, the best option.
|
# ? Aug 13, 2021 07:29 |
|
Coming from a Lisp background, I always hesitate to call them macros. Let's just #define macro text_replacement.
|
# ? Aug 13, 2021 09:47 |
|
Xarn posted:What kind of macros? What are they doing? Mostly basic stuff, min, max, abs, squares, cubes, root sum squares. Things that could be and should be done in real functions, but I'm mostly curious if there's a performance cost of switching them to templates.
|
# ? Aug 13, 2021 18:14 |
|
Is there an open source telemetry tool that works in ANSI C? We could use it for internal megacorp tools but this team has some olds obsessed with using some vetted, public one. It looks to me like tracking on the system is just anathema to the whole open source culture, so there are some toys out there, but nothing I could act like is popular and we'll supported.
|
# ? Aug 13, 2021 18:20 |
|
PittTheElder posted:Mostly basic stuff, min, max, abs, squares, cubes, root sum squares. Same performance. Take a look at the implementation of std::min as an example. Probably looks identical to your macro. It’s inlined. The only difference is the parameters’ types are enforced by the compiler.
|
# ? Aug 14, 2021 00:33 |
|
That's actually a funny example because for a very long time std::min() was really slow in VC++. It is now finally fixed, though.
|
# ? Aug 14, 2021 00:57 |
|
C++ code:
|
# ? Aug 18, 2021 23:01 |
|
Is there a convention in C for communicating that a pointer is referring to a value the function will allocate and the user must free? This kind of thing is kind of lovely but I'm not always dealing with atomic calls where they can call once to get a size, allocate it themselves, and then call again with the buffer. That would be more ideal because the mallocs and frees properly pair. All I can really lean on is "writing some sentences" which is fine but I was hoping at least for a function header standard or term to use on stuff like that and get into the habit of using that too.
|
# ? Aug 19, 2021 05:51 |
|
Rocko Bonaparte posted:Is there a convention in C for communicating that a pointer is referring to a value the function will allocate and the user must free? This kind of thing is kind of lovely but I'm not always dealing with atomic calls where they can call once to get a size, allocate it themselves, and then call again with the buffer. That would be more ideal because the mallocs and frees properly pair. Dunno about convention, but in C when I provide a create function, I also provide a destroy, even if it just calls free. This also allows you to easily change the allocation strategy without hunting down all the frees you need to change. e: I also try to put the create and destroy function declarations near each other and mention the destroy function in the documentation of the create function. That’s worked well enough for me. chglcu fucked around with this message at 06:19 on Aug 19, 2021 |
# ? Aug 19, 2021 06:11 |
|
chglcu posted:Dunno about convention, but in C when I provide a create function, I also provide a destroy, even if it just calls free. This also allows you to easily change the allocation strategy without hunting down all the frees you need to change. I also do this. It seems to work pretty well. I've also sometimes included custom allocator support via function pointer parameter for alloc/free.
|
# ? Aug 19, 2021 17:42 |
|
Can somebody direct me towards best practices for C project organization? I keep just seeing a ton of .c and .h files in a flat directory, and thinking there must be a better way to do this.
|
# ? Aug 27, 2021 17:51 |
|
Twerk from Home posted:Can somebody direct me towards best practices for C project organization? I keep just seeing a ton of .c and .h files in a flat directory, and thinking there must be a better way to do this. Honestly just do the same poo poo as you would in any other language. Separate your functionality logically into separatable modules that hold contracts with each other, separate the files along the same lines, etc. Just like you would in python or anything else. Could do worse than looking at big c projects like the linux kernel or systemd or something.
|
# ? Aug 27, 2021 19:38 |
|
Phobeste posted:Honestly just do the same poo poo as you would in any other language. Separate your functionality logically into separatable modules that hold contracts with each other, separate the files along the same lines, etc. Just like you would in python or anything else. Could do worse than looking at big c projects like the linux kernel or systemd or something. Awesome, thanks for this. https://github.com/systemd/systemd/blob/main/docs/ARCHITECTURE.md is exactly the kind of thing that I was looking for, even though the projects I'm dealing with are unlikely to get to a fraction of the size.
|
# ? Aug 27, 2021 19:40 |
|
I could've sworn there was a whitepaper out there about library-oriented development in LLVM, but yeah, the general idea of Always Be Writing A Library isn't a bad one. You should always be thinking about interfaces between subsystems and who has responsibility for what, and if you do that, you'll find it natural enough to split subsystems into their own directories. The three caveats:
|
# ? Aug 27, 2021 19:59 |
|
rjmccall posted:
Mozilla really needed you in 1999!
|
# ? Aug 28, 2021 14:17 |
|
Does anyone have a link to an enum set and map utility? We have a bunch of dense enums we make tables based on for some reasonably high perf code and I’m tired of writing switch statements to map enums to structures. I wrote my own based on bitset (for set) and an array for the map values, but I’d prefer something someone else maintains if possible. Having trouble searching for it, maybe no one has this issue and I’m inventing solutions to problems which don’t exist?
|
# ? Aug 28, 2021 14:26 |
|
Look into X macros.
|
# ? Aug 28, 2021 14:41 |
|
ultrafilter posted:Look into X macros. I should have mentioned modern c++, we use some x macros, but tbh it feels a bit grodier than a nice constexpr map with all the nice collections stuff you get with typical c++ structures.
|
# ? Aug 28, 2021 14:47 |
|
Those implementations seem reasonable enough, although I guess you could use a fixed-width bitset/array if you knew the bounds if the enum. Is that what you want, something metaprogrammed to do that optimization, or do you just want something that does the casts for you?
|
# ? Aug 28, 2021 18:26 |
|
rjmccall posted:Those implementations seem reasonable enough, although I guess you could use a fixed-width bitset/array if you knew the bounds if the enum. Is that what you want, something metaprogrammed to do that optimization, or do you just want something that does the casts for you? I’m manually passing the bounds (we have the max for everything), so that’s fine and it’s all fixed width. Just seeing if I missed something that does this for me and I could search well enough. Something dealing with casts and handles filling out the while map/container interface for me so I don’t have to do it myself would be nice. There are always little gotchas with these sorts of things and I’d rather someone else thought about them, if possible. This just seems like the kind of micro optimization someone would have done somewhere already, so I’m surprised I can’t find it. Maybe it’s too micro even for c++ template loves
|
# ? Aug 28, 2021 20:42 |
|
Maybe magic_enum might help? It doesn't give you sets and maps out of the box but it may serve as a building block.
|
# ? Aug 28, 2021 21:52 |
|
Sweeper posted:I’m manually passing the bounds (we have the max for everything), so that’s fine and it’s all fixed width. Just seeing if I missed something that does this for me and I could search well enough. Something dealing with casts and handles filling out the while map/container interface for me so I don’t have to do it myself would be nice. There are always little gotchas with these sorts of things and I’d rather someone else thought about them, if possible. I am not enough of a C++ expert to know if what you want is built in, but if you’re doing the same thing over and over you might consider a code generation template. Our group used jinja to generate C++ code and it seemed to work well. Certainly better than doing everything by hand.
|
# ? Aug 28, 2021 22:40 |
|
I don’t know of a library for exactly that off-hand. We do have one in the Swift compiler that assumes the enumerator values are already shifted.
|
# ? Aug 29, 2021 06:43 |
|
Is https://github.com/DLTcollab/sse2neon a decent way to go for getting code that is directly importing SSE intrinsics (<emmintrin.h>) working on arm64? I'm just shoving it in there like this. Things are building & running, but I don't have great confidence that I'm using the appropriate type of ARM uarch or the full SIMD capabilities of the Apple M1 & friends. code:
|
# ? Aug 29, 2021 19:29 |
|
|
# ? Jun 2, 2024 11:49 |
|
I have multiple variables packed together in a memory buffer that I'd like to assign to a struct. Are there any gotchas for this beyond some basic memory alignment stuff? What I want to assume is: 1. The memory for a struct is going to start at a proper alignment. 2. The amount of padding then depends on the next variable in the struct. It would be aligned on cleanly divisible boundaries based on that type's width. So a char and then a (32-bit) int would imply I have to skip 3 bytes before dealing with the integer in the struct. I know the actual schema of the data when I'm doing this. I didn't know if there was any other major things to worry about before I create a segfault generator here. Also, I'd rather not get into X instead of Y either unless you want to read a pile on how I got here.
|
# ? Sep 2, 2021 23:10 |