Strings are typically represented in memory by the integer address at or near the first character of the string. Typically concatenation involves allocating new memory with enough room for both strings then transferring the bytes of both to the new location.
Strings A and B might be concatenated by a special operator such as A || B or by a String specific interpretation of the addition operator A + B.
The space allocated to a string can be stored as an integer as part of a prefix to the string or as a special sentinel value at the end. Classically C uses a zero-byte as the sentinel which complicates concatenation because the non-zero characters of both strings must be counted to know how much space to allocate for the combined string.
Repeatedly adding single characters to a long string can lead to many sentinel searches and many storage allocations. Some languages offer a String Buffer type that is internally optimized for this operation by preallocating more memory than initially needed.