For added hilarity, you can do it entirely without getting your hands or the standard library's hands dirty with pesky loops and let the compiler do the hard work:
#include <stdio.h>
#include <stdlib.h>
int main() {
char a[20] = "Hello World today!!";
char* const p = malloc(sizeof a);
union {
char* volatile p;
struct {
char a[20];
}* s;
} destination = {.p = p}, source = {.p = a};
*destination.s = *source.s;
printf("%s\n",p);
return 0;
}
// tested with CFLAGS:='-Wall -Wextra -pedantic -std=c11'
Although it should be mentionend that this is not technically compliant with the C standard specification, because we're hiding a cast by using a union and the standard doesn't allow us to use unions in this way (you have to promise to only use the union member that you last wrote to, which we break when using the s
member).
But it's more fun than using the library or those loop things, don't you agree? :)
(Disclaimer: This is using loops, too (or rather implicitly unrolled loops). We just don't see them.)
Edit I was just curious and had a look at what clang (3.2, rather dated, granted) generates from this and it seems to actually translate this into a memcpy call (last line).
%1 = alloca i32, align 4
%a = alloca [20 x i8], align 16
%p = alloca i8*, align 8
%destination = alloca %union.anon, align 8
%source = alloca %union.anon, align 8
store i32 0, i32* %1
%2 = bitcast [20 x i8]* %a to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* getelementptr inbounds ([20 x i8]* @main.a, i32 0, i32 0), i64 20, i32 16, i1 false)
%3 = call noalias i8* @malloc(i64 20) nounwind
store i8* %3, i8** %p, align 8
%4 = bitcast %union.anon* %destination to i8**
%5 = load i8** %p, align 8
store volatile i8* %5, i8** %4, align 8
%6 = bitcast %union.anon* %source to i8**
%7 = getelementptr inbounds [20 x i8]* %a, i32 0, i32 0
store volatile i8* %7, i8** %6, align 8
%8 = bitcast %union.anon* %destination to %struct.anon**
%9 = load %struct.anon** %8, align 8
%10 = bitcast %union.anon* %source to %struct.anon**
%11 = load %struct.anon** %10, align 8
%12 = bitcast %struct.anon* %9 to i8*
%13 = bitcast %struct.anon* %11 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %12, i8* %13, i64 20, i32 1, i1 false)