Is it possible to convert C to unsafe Rust?

So I made a simple "hello world" in C

#include <stdio.h>
int main()
{
	int x = 10;
	printf("Hello, World!");
	return 0;
}

I was wondering if there was a program to convert C code to Rust without it being messy code?

Yes, with preserving all the exact semantics of the original C code.

https://c2rust.com/manual/

5 Likes

It's possible to convert C to unsafe Rust, but it's going to look ugly in Rust in general because of all the random little things that happen in C and unsafe in Rust has more syntactic markers.

For example, short x = 1; ++x; in C becomes, if directly translated to Rust,

let mut x: i16 = 1_i32 as i16;
x = ( (x as i32) + 1_i32 ) as i16;

And that's assuming you're ok with losing the "overflow is UB" semantic. If you want that, then you're looking at something like

x = unsafe { i32::checked_add(x as i32, 1_i32).unwrap_or_else(|| std::hint::unreachable_unchecked()) as i16 };

to be a fully-faithful translation.

EDIT: forgot a mut

Is this c2rust?

Why wouldn't it just translate to something like this:

let x: u8 = 1;
x += 1;

Because short isn't u8, at least.

Oh, is it i16?

Honestly it depends. The C specification doesn't specify the bit width of most of its primitive universally. So it vary over platforms. But on x86/arm/riscv/powerpc with both 32/64bit archs at least the short in C is 16bits wide signed integer.

1 Like

Certainly in the very simple example I picked it could be simplified, but in general it's important that all the little nuances be reflected in order for the semantics to be the same.

For example, try running these similar-looking C (run online: https://gcc.godbolt.org/z/KxjaqGz8r)

int main() {
    signed char x = 127;
    x = (x + 1) / 2;
    printf("%i", (int)x);
    return 0;
}

and Rust (run online: https://rust.godbolt.org/z/9a5xh749P) programs

fn main() {
    let mut x: i8 = 127;
    x = (x + 1) / 2;
    dbg!(x);
}

Do they print the same thing? Why or why not?

3 Likes