Looks like a bug (whether documentation or code) as read-kbd-macro
still claims to return a string if possible, but nowadays it forcibly returns a vector. Please M-x report-emacs-bug
to get that clarified.
You could extract a string of characters from the vector:
(mapconcat (lambda (event)
(and (characterp event)
(char-to-string event)))
(read-kbd-macro "C-c"))
But if you look at the code for read-kbd-macro
you'll see that it calls this:
(defun edmacro-parse-keys (string &optional _need-vector)
(let ((result (kbd string)))
(if (stringp result)
(seq-into result 'vector)
result)))
Hence the string value you wanted is coming from kbd
:
(kbd "C-c") => "^C"
There are of course arguments you can pass to kbd
which won't return a string, but that would always have been the case for your code, and presumably you're not attempting to use any of those.