There are some architectures that C supports better than Rust due to having gcc's backends as an option as well as LLVM, but within a given architecture that both support, I don't think there is.
Only thing that comes to mind immediately is VLA/alloca but I'd have to check. Most of the gnarly pointer things are fair game and work just as well as their C counterparts.
VLA are thankfully no longer required for ISO C compliance, who had thought it was a good idea in first place?
Google even sponsored the work to clean the Linux kernel from them.
Rust supports VLAs, Box<[T]> is pretty common in fact. It just doesn’t have a native way to alloc them on the stack.
> Is there anything that can be done in C that can’t be done in unsafe Rust?
Duff's device <https://en.wikipedia.org/wiki/Duff's_device>.
Re:Why Is C Faster Than Java (2009)
by josephcsible on Sunday December 26, 2021 @11:55PM
(#29699421)
You're mixing up a thing you can do with a way that you can do something. You can write Rust code with the same observable behavior as Duff's device in C.
Also, Duff’s device is pretty terrible and a modern compiler will output much better code.
> You're mixing up a thing you can do with a way that you can do something.
I don't think they are.
> You can write Rust code with the same observable behavior as Duff's device in C.
Yes, turing complete languages can do that.
A good example of cool tricks to impress fellow hackers that have no place in code bases that should meet certain quality levels of long term maintenance.
Modifying memory on the heap in multiple threads without a mutex, from one pointer.
Why anyone would want that on purpose, I don't know.
Re:Why Is C Faster Than Java (2009)
by umanwizard on Monday December 27, 2021 @12:17AM
(#29699536)
What stops you from doing this in Rust?
The language itself, unless you go out of your way to circumvent the protections with `unsafe`.
In this particular case it's the `Sync` trait and the generell rules around sharing data.
Re:Why Is C Faster Than Java (2009)
by umanwizard on Monday December 27, 2021 @03:23AM
(#29700575)
> unless you go out of your way to circumvent the protections with `unsafe`
I was specifically referring to the things you can do in `unsafe` blocks.
It was my impression that you can't do it even in unsafe because ownership rules still apply. But apparently I was wrong and there is a way to do it?
Re:Why Is C Faster Than Java (2009)
by umanwizard on Monday December 27, 2021 @12:34PM
(#29704581)
Ownership rules still apply _to references_, but not to raw pointers.
This program prints "12". The only difficulty is that Rust's designers have intentionally made this pattern difficult by marking raw pointers as !Send, but you can get around that by wrapping them in a Send type.
use std::{time::Duration, ops::{DerefMut, Deref}};
struct SendWrapper<T>(*mut T);
impl<T> Deref for SendWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.0.as_ref() }.unwrap()
}
}
impl<T> DerefMut for SendWrapper<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.0.as_mut() }.unwrap()
}
}
unsafe impl<T> Send for SendWrapper<T> {}
fn main() {
let mut x = 10;
let p1: *mut usize = &mut x;
let p2: *mut usize = &mut x;
let mut s1 = SendWrapper(p1);
let mut s2 = SendWrapper(p2);
let j1 = std::thread::spawn(move || {
*s1.deref_mut() += 1;
});
let j2 = std::thread::spawn(move || {
std::thread::sleep(Duration::from_secs(1));
*s2.deref_mut() += 1;
});
j1.join().unwrap();
j2.join().unwrap();
println!("x: {}", x);
}
Re:Why Is C Faster Than Java (2009)
by perryizgr8 on Monday December 27, 2021 @12:31AM
(#29699645)
There are many benefits. Here is a good video that explains:
Re:Why Is C Faster Than Java (2009)
by unrealhoang on Monday December 27, 2021 @01:05AM
(#29699892)
Rust does have UnsafeCell for gurus/experts to build such complex concurrency building blocks, pack it in a safe API for us plebs to use.
So does Rust, in unsafe blocks. Is there anything that can be done in C that can’t be done in unsafe Rust?