There is a solution to actually display a surface with a half-pixel precision. There is a performance cost but it renders quite nicely. This is basically how old-school anti-aliasing works: rendering at a higher resolution then downscaling.
win = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, 0); //create a new rendering window
renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); //create a new renderer
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother.
SDL_RenderSetLogicalSize(renderer, width*2, height*2); //tell the renderer to work internally with this size, it will be scaled back when displayed on your screen
You can find some explanation about the functions here or on the API page here and here.
Now you can use your window as if it was twice bigger but it still outputs at the same size. When you're doing your output, you put the same SDL_Rect in the blitting functions except everything is doubled. That way you can keep half pixel precision. You can get even cleaner output if your sprites have also the increased precision.
You could also do it with quarter pixel precision but the performance cost will be even bigger so it might not be possible in your application. There is also a memory cost because the surfaces are bigger (times four for half pixel precision, sixteen for quarter pixel).