malloc으로 동적 할당했기 때문에 구조체의 시작 위치는 (Heap 내에서) 어느 곳이든 상관 없습니다. 따라서 arr[0] 구조체 다음에 arr[1] 구조체가 반드시 36바이트 뒤에 오지는 않습니다.
저의 경우 64비트 컴파일러를 쓰기 때문에, 왼쪽의 값이 40바이트가 아닌 44 바이트씩 증가합니다.
그리고 (*((ptr)+0)).x 는 단순한 Pointer 연산일 뿐입니다. (((*ptr)+1)).x 의 경우에, (ptr)+1을 하면 Str 크기(36바이트)만큼 주소를 증가시키고, 여기에 (((*ptr)+0)).x 를 해서 x를 참조하면 C에서는 (((ptr)+1)+0) 을 수행해줍니다.
즉, 배열처럼 구조체 참조도 단순한 포인터 연산으로 변경되기 때문에 (((ptr)+0)).x의 경우에는 36바이트 증가하는 것이 맞습니다.
( (((*ptr)+0)).y 의 경우 (((*ptr)+1)+10) 을 수행하게 됩니다. )