#C Lang Question
1 messages · Page 1 of 1 (latest)
<@&987246683568103514> please have a look, thanks.
Here is an AI assisted attempt to answer your question 🤖. Maybe it helps! In any case, a human is on the way 👍. To continue talking to the AI, you can use </chatgpt:1108714622413963314>.
r web development. Can someone provide some insight on where C is commonly used and why it might be a good language to learn even if you primarily work in backend development?
Answer:
C is a powerful, low-level programming language commonly used in systems programming, embedded systems, and performance-critical applications. It is often used in developing operating systems, device drivers, game engines, and high-performance computing applications.
Learning C can provide a solid foundation for understanding how computers work at a low level, as well as improve your problem-solving skills and programming efficiency. Additionally, many modern programming languages like C++, Java, and Python are influenced by C's syntax and principles.
Even if you primarily work in backend development with languages like Java or C++, learning C can give you a deeper understanding of how software interacts with hardware and help you write more efficient code. It can also open up opportunities to work on projects that require low-level optimizations or close interaction with hardware components.
Overall, learning C can be beneficial for expanding your skill set as a backend developer and improving your understanding of computer systems and performance optimization.
id say C is mostly used on stuff like chips, embedded stuff
hardware-near topics
robots, microcontrollers
logic for a dimmable lamp and so on
u definitely wont find use for it in the backend sector
i know a few companies that use c++ for backend. but that choice was then usually made for other reasons and imo its not a good decision
ive been doing c++ regular backend dev for a few years at a company and we constantly had to reinvent the wheel
C is mostly used for:
- embedded
- compilers
- OSes
- drivers
if you're trying to build a shiny website with it then you're probably not going to get far
Not looking to build a shiny website but are there any use cases for it on the backend, ie it as a web socket server
id say no
that would be a good use for java
especially the http/tcp stuff is extremely annoying with it
I’m mostly looking for best projects that would aid in the process of learning but also be fun
you can try making your own operating system
it sounds scary but doing step one isnt that difficult
or try making a compiler
C excels at those tasks the most
see, u cant even send a simple http request. u first have to study win api avoid tcp sockets. then write http urself ontop on windows tcp api...
u have nothing at hand for these typical backend things
u want to connect to a database? great, plan in 3 months until uve written the necessary boilerplate
u cant just slap sth like "spring ecosystem" on it and all ur backend problems are solved
library moment
Yeah
C is a fairly raw experience
its not difficult to learn btw as there just isnt too much to it
it might be difficult to use or debug as u run into complex problems. but the language itself is fairly straightforward
So mostly start with cli stuff?
the only difficult parts are maybe pointers, stack vs heap, malloc realloc free, and unions
if u know java then all u really have to learn is what liquid just said
which u understand after 2 days of practice
and perhaps after a week ur fairly comfortable with it
that's all C u might want to know if u dont plan on doing any C anyways
tbh things like C just take a lot of practice to get used to
you have to think outside the box a lot about problems
I thought I might play around with embedded stuff in the future but I don’t have any immediate ideas
(and get used to magic values (i.e 0xFFFFAAA or wtv), they can be useful)
Which ik that’s a whole concept
langdev is fun
Pointers
Yeah, these can be difficult to understand, but if C isn't your first language you can wrap your head around it within a few days.
Stack vs Heap
That's not a thing. Nowhere in the C standard does it ever mention a stack and/or heap. That's CPU/OS specific.
[m|c|re]allocandfree
I would say that these are relatively easy to grasp once you understand pointers andsizeof. Especially for beginner projects, compiling with-g3 -fsanitize=address, i.e., using address sanitizer, typically catches most errors related to theallocfamily.
union
Yeah... These are extremely hard to properly understand. I'm sure as hell not comfortable using them and I think most people aren't.
I would also add the entire (meta-)build process as one of the things one needs to learn, i.e. Makefiles and CMake, + installing & using Linux, either via WSL or native.
An incredible difficult part of the language, that wasn't mentioned so far, are macros.
Note that java has union too
Wait, what?
You mean like sealed interfaces or what?
it does?
Or is it some Unsafe hack?
I am pretty sure there is no union in java
yeah, same
yes
ah, kk
how are they related to union?
they are unions
They were created for the purpose of being unions
I dont get it
you can do smth like this:
sealed interface Union permits A, B { }
Union union = whatever;
switch (union) {
case A a -> System.out.println(a.foo());
case B b -> System.out.println(b.bar());
}
```[Source](<https://www.reddit.com/r/java/comments/1ef4kxn/comment/lfijiw0/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button>)
I dont see how that is related to unions, but maybe I misunderstood them in C
arent they just some kind of struct, but they are only as big as the largest member and only store that much information at any point?
true, it's not a C like union
forget the memory part, that's not really the point of an union
hm then I actually misunderstood them in C ig
I mean
the idea is to have a struct that can either have a field or another
but not both at the same time
the equivalent in rust would be enums
ah ok then I guess this kinda fits
A union is a way to access the same byte sequences as different data types.
E.g. you can do:
#include <stdio.h>
#include <string.h>
union A {
int val;
char bytes[sizeof(int)];
};
void print(union A a) {
printf("val: %d\n", a.val);
for (int i = 0; i < sizeof a.bytes; i++) {
printf("%x, ", a.bytes[i]);
}
puts("");
}
int main() {
union A a;
a.val = 4;
print(a);
puts("-------");
strcpy(a.bytes, "abc");
print(a);
}
```to get this output:
```c
val: 4
4, 0, 0, 0,
-------
val: 6513249
61, 62, 63, 0,
and yeah, the value 4 is internally stored as 0x0400'0000, not as 0x0000'0004 because that system is a little endian system
yeah I understood that, but I dont really have a use case in mind personally
Check the first two answers here: https://stackoverflow.com/questions/252552/why-do-we-need-c-unions
dude, it depends on how you're taught the concepts. Stack vs Heap is a real thing that C people should know
are you suggesting that new C people should not learn the difference?
C unions are basically union types
it works exactly like a struct, except all of its members are located at a single memory address (structs have each of their members at different addresses to avoid corruption)
im pretty comfortable using unions when necessary
Pointers are not hard. They're pretty much just an address stored in a variable
but, the twist is, that you can go to the address (by *ptr) and get the value of the variable of that address
they are suggesting that its not specified. so while for example windows might often do it like that, theres a good chance some embedded chip will do it entirely different. and that's indeed the caseythe exact way the memory is maintained below ahat C has access to differs in practice
ofc its important to learn about stack vs heap memory. but its also good if u know that this is just one way how a os might handle it
yeah, OSes have a stack vs heap difference, i think thats extremely important
see, its totally valid for an OS to not offer stack and heap memory but instead use a database for all memory instead
then what u would say in C is stack or heap memory is in fact both just a database
with no difference at all
C itself doesnt specify stack vs heap. it doesn't say that when u use malloc that ull get "heap memory"
that's for the OS to decide how it wants to do malloc under the hood
while this isn't an important point to make for sth like windows, it does become important when u make microchips for cars or robots for example
as in these environments its pretty common to have custom memory models
or when u work on OS interfaces, custom OS and compilers
its good to keep it in mind i guess
but not super relevant. in particular not for a beginner
dude, i meant it as an important concept
yes its an important concept.
its just that while its a commonly used system, not everyone uses it. and its worth knowing that not everything follows that idea
so do you just choose to not learn it at all then?
its worth knowing that when u malloc or create sth "on the stack" that it doesnt necessarily mean that it will follow that concept/idea. and in some cases there might even be no distinction at all.
nah, that's definitely not what i said
or wanted to imply
I agree that stack & heap is an important concept in general, but not for C.
All you need to know for C is that the alloc family allocates memory and the free function frees it. You don't need to care about any of the actual details.
important concept in general, but not for C.
C is where it becomes important
You don't need to care about any of the actual details.
You sort of need to care about the details in order to have proper program speed, prevent UB, etc.
struct* vs struct in variables
You sort of need to care about the details in order to have proper program speed
Sure, totally agree
You sort of need to care about the details in order to prevent UB
No, absolutely not.
struct* vs struct in variables. this is a stack variable, you don't need to worry about mallocing or freeing, you just initialize it (and your program can get faster as a result)
if you were to return &src_p from the function, then its UB because its a stack variable. it reaches end of life when the scope leaves
struct*
knowing about the actual details about the stack and heap here would be pretty useful, and i just explained why
if you don't want returning &src_p to be UB, then just make it allocated and return src_p.
i said sort of, i didn't say to sweat about it, just keep it in mind
prevent UB
Opposite, you don't need to know that if you want to prevent UB, you need to know that if you want to exploit UB
have proper program speed
Not only speed isn't a priority, how does knowing that helps you write faster programs ?And at this point, you should also learn about cache misses, vectorization, etc. And there are so many things that you are not longer following a c course but a OS course, and this knowledge is generic for any language, not just C... and at the end, exploiting that is exploiting UB...
what are you talking about 🙏 UB is very easy to come across in C
This is just knowing that malloc means you have to free at some point
exploiting UB is cool
This is just knowing scope
this has nothing to do with heap/stack
you don't need such knowledge
And knowing heap/stack has nothing to do with avoiding them
C is known for manual memory management (malloc, free)
why not know those details? are you recommending to just not learn them at all? what if you want to program on an OS?
and heap/stack knowledge isn't needed for that, as zabu already explained
malloc is heap
Then you need to follow a OS course, not a C course
In fact, you don't need to use C to code an OS
Please read again what zabu said, we are just repeating atthis point
no crap you don't need C
you can use assembly for all i care
or even java
embedded
Actually you can't use java alone
i just threw it out there, i know about javas requirements
C++ would be better
yeah i saw where i got lost
No, that's not UB in itself. Simply returning that from a function would be a dangling pointer.
Only once you dereference that dangling pointer, only that's when you have UB.
It's the same for strict aliasing.
Doing this:
int x = 4;
float *yp = (float *) &x;
```is completely legal. An example of where we can see this is when we have `struct sockaddr_in` and need to cast that to `struct sockaddr` to pass to our networking functions.
Only once you do:
```c
int x = 4;
float *yp = (float *) &x;
float y = *yp;
```, i.e. only once you dereference `yp` do you actually have UB.
dangling pointer can result in UB
Yeah... if you dereference it... like I said
not if you null it out
dereferencing is the only way to access the "data" here, I understand that its just an address
if you just return src_p then thats copying the struct
i was arguing for knowing stack vs heap, I know that stack and heap are just regions of one memory
Because in C you have the ability to choose to allocate on the stack or heap, you need to know how they do the memory allocation and where. Because if you dont you can make your program needlesly slow.
and exactly which data to allocate where
this is what i was saying, i was arguing about awareness of it and using it on OSes, and it is an OS tied thing
Not only speed isn't a priority, how does knowing that helps you write faster programs
For example if you know that the entireallocfamily is very slow on your current hard-/software, then you can avoid dynamic memory allocation as much as possible by e.g. using stack buffers.
Alternatively, if you know that theallocfamily will do a best effort at allocating memory sequentially (i.e. a 2ndalloccall would allocate the bytes immediately after the previousalloccall if possible), then you may be able to "abuse" that, to get e.g. faster lookup times in a list (because of fewer cache misses and even possibly some attempts at vectorization [obviously with safety checks and fallbacks]).
At least that'd be my first intuition as for why knowing that could help us improve runtime performance
🙂
stack buffers
alloc is arena with extra steps if im not wrong
well... The glibc one is.
But obviously malloc depends on the implementation.
The glibc memory allocator is very good when it comes to single-threaded performance. Here's a proper explanation on how it works: https://sourceware.org/glibc/wiki/MallocInternals
The glibc allocator is very good in terms of single-threaded performance, but for multi-threaded programs it can become a bottleneck. Also in some scenarios you may desire a specific alloc behaviour, in which case a more specialized version would be better for you.
An example for a memory allocator optimized for multi-threaded program would be Hoard: https://www.cs.utexas.edu/~mckinley/papers/asplos-2000.pdf
Ik how it works, i guess it was a gross oversimplification
"heap" is just stack buffers that work like an arena
the memory stays until the OS decides to terminate it or until its freed
Ik how it works
Really? Wow. I read it once or twice but it's just so complex that once or twice is not barely enough to fully understand it.
I actually had to write my own [m|c|re]alloc and free functions for a homework assignment once. Lemme see if I can find it
ohhh i think you're talking about like
the inner details of it
i was talking more broadly
Yeah, this was my allocation method 🐒
It was very, very trivial:
/*
The memory allocation is pretty simple:
We have a heap that starts at a base and ends at a end (non-inclusive)
Each chunk of malloc(size)'d memory looks like so:
[METADATA][USER_DATA]
8 bytes size bytes
The METADATA is structured like so:
[FREE][SIZE]
1 bit 63 bits
Consequences are that we can only allocate memory of up to 2^63 bytes, instead of 2^64 bytes.
One could have used only the lower 61 bits and treated it as a size * ALIGNMENT (= 8) to
get the full 2^64 bytes, but 2^63 is easily sufficient.
For our allocation policy we're using best-fit, that is we're searching through our entire list
so that we find the smallest piece of memory that fits our needs.
If we find such a chunk, then we use it and potentially reduce the size to fit our current allocation.
If we had to reduce the chunk's size, then we also need to create another freed chunk past the current one
to account for the reduced size.
If no such chunk exists then we need to extend our heap.
Merging is attempted on every single free-call.
[m|c|re]alloc returns a pointer to USER_DATA, i.e. we have 8 overhead bytes per allocated memory chunk,
which is exactly one extra alignment thing + up to 7 padding bytes to meet the alignment requirements.
*/
malloc in libraries usually rely on kernel funcs
tldr; its magic
yeah
i havent actually went out and written my own malloc yet
"kernel functions"... I can call these if I include sys/mman.h and unistd.h
Was actually pretty dope to see everything working despite it being my own implementation.
And we didn't just write:
void *my_malloc(...) { ... }
...
```but we actually wrote
```c
void *malloc(...) { ... }
```and `LD_PRELOAD`ed them, so that our functions literally replaced the allocation functions that the entire standard library was calling.
im writing a probably shit malloc rn
i fucking hate how clion does cmake
i usually use makefile
this is p hard
would this be bad
im trying to think of my own solution
i think chunks are the key to this
Honestly, who cares if it's bad. My incredibly simple implementation still took me more than a day.
What I'm concerned about with your approach is the bookkeeping. How do you keep track of what chunks are or aren't free, how do you keep track of how many bytes each malloc really requested, or do you just hand it out in baches of 128 bytes?
*Okay, nvm my question about whether or not you're handing it out in 128b chunks per alloc call. So, you actually do want to store multiple allocations per chunk if possible. Then how/where do you store all that data? You can't just put meta-data in front of every chunk, because allocated memory needs to be sequential, so if someone were to allocate e.g. 512 bytes at once, then you need to guarantee that the returned data is sequential, and in particular, doesn't contain any metadata for other chunks.
Also remember that you can't just malloc some memory to store that metadata, because you're writing the malloc right now (I fell into that pitfall initially 🐒 ).
i keep track of chunks are free or not by in_use variable, and I want to keep the allocations seperate to reduce any sort of clusterfuck happening
I'm designing this so the data is completely sequential, no gaps
i should reduce the chunk size to 64 bytes though to reduce the amount of memory wasted
I think you forgot about free 🐒
i literally have free in the image
Also once you handed out memory, you can't shuffle it around in the chunks anymore
Because then that would invalidate the pointer the user has
so i search for more places to place it
I meant this comment of yours:
yeeeeeah so i would search for more places to put it then
i forgot about pointers
What is the in_use variable? Keep in mind that you may need to store information about thousands or millions of alloc calls, without being able to dynamically allocate memory yourself for bookkeeping, so idk how you want to have a single variable handle all of that.
no, in each chunk
my code atm
The issue is that you can at most allocate 8 * 64B = 512B with your alloc function right now, and it's not even dynamically, but statically allocated.
Also, regardless of how big you make it, it will always have an upper limit (+ it has an incredible memory overhead).
how would dynamic allocation work
the same without a static keyword?
By using sbrk or mmap
I literally don't know of any other ways
im tryna skip all of that
and do it raw
im doing it like a custom OS
I mean, then you should know what CustomOS™ function you need to call to allocate memory. I can only tell you how it works for Linux.
Perhaps this conversation should be in #geek-speak instead
yall think it'd be better to just do C++?
or should I start with C and learn that after
it really depends on ur goals
its like ur asking "should i learn chinese or spanish next?"
well, if u plan on moving to china then probably chinese first
if u plan on becoming a spanish teacher then spanish first
fair enough, I mostly want to be able to understand how more stuff works even if I don't end up using it for anything meaningful
and be prepared for college level cs classes which I thought involved a decent bit of C/C++
c++ is a complex language. definitely more stuff to learn language-wise than for C
its more on the level of other high level languages like java/python/c#
when it comes to language features

it deals a lot with ownership questions and expressing intention explicitly when it comes to passing stuff around
for example raw-pointers are replaced with 3 new options called smart-pointers
std::shared_ptr, std::unique_ptr, std::weak_ptr
additionally u have references Foo&
perfect-forwarding references Foo&&
constructs like std::move
and a whole lot of shenanigans when it comes to templates ("generics")
a lot of pitfalls that run into UB
for example when u go for inheritance and forget to mark ur destructor virtual. or when u create an array and forget to fill it with explicit values before using it
just to name two things that happened to me last week