0

I am working with the const char * type in C. Due to the libraries I am using I am trying not to use or include other libraries (namely cstring). The function I am working in is passed a buffer of type const char *. I want to append a finite message to the end of this buffer.

For example:

functionA (const char *buffer){
    char *message = "hello world";
    //code appending message to the end of buffer
    //buffer now contains its original contents plus "hello world" at the end.
}

I am thinking the best approach is to create a temporary variable to take in the data from the buffer, and then add the message. Once that is done, reassign the buffer pointer to the temporary variable's reference (as I am trying to do this with the least amount of alterations to the function, to reduce the chance of a compile error).

Mark Elliot
  • 75,278
  • 22
  • 140
  • 160
user749681
  • 1
  • 1
  • 1
  • 3
    `buffer` is a *constant*. Are you expecting to be able to change the string pointed to by `buffer`? If so, on what basis? – Greg Hewgill May 12 '11 at 00:30
  • 1
    Why not use string.h (especially strcat), it's part of the C standard library, so it is part of EVERY c programming environment and no real dependency. For example for memory allocation you also need the standard library, so without it you won't go far. – Christian Rau May 12 '11 at 00:31
  • 1
    Just about everything about this is mistaken or confused, from "I am working with the const char * type" to "to reduce the chance of a compile error". One works with the types that are appropriate to the problem, not with pre-specified types, and compile errors are not a matter of "chance" -- you "reduce the chance" of compile errors by coding correctly. You can try to proceed from the responses you have received below, but I predict that you will have a very hard time of it until you get a clearer conceptual framework. – Jim Balter May 12 '11 at 02:40

9 Answers9

4

You can not append to const char *. Because it's constant.

Mel
  • 6,077
  • 1
  • 15
  • 12
  • Technically, you can cast it to `char*`, but that completely defeats the pupose of declaring it as `const char*` to begin with (and is likely to confuse your compiler). Might be useful if you only have to declare it as `const char*` to match some idiot's API, though. – David X May 12 '11 at 01:48
  • 1
    No, what you *can* do is hand it off to another function as a casted char * that then does the concatenation for you. Your function cannot "assign to read-only location". You can cast to char * on assignment to a local variable, which will allow you to modify the local var pointing to the same memory, but since you promised not to do that in your declaration, your consumers are free to assume you have done nothing of the kind and overwrite your memory with the strlen() they remembered before handing it over to you. – Mel May 12 '11 at 02:11
  • I was refering to the assignment to a local variable (eg: `char* mbuf = (char*)buffer;`), but you could also do it inline as `((char*)buffer)[i] = '?';` (ie, assign to a read-only location). Still nearly always a bad idea, of course. – David X May 12 '11 at 02:20
  • 1
    Unless the array the `const char *` points to happened to be non-`const`-qualified and a non-string-literal, casting away the `const` to modify the object results in *undefined behavior*, i.e. saying you "can do it" is simply wrong. – R.. GitHub STOP HELPING ICE May 12 '11 at 02:52
  • @R.., yes, that's what I meant by "defeats the purpose", since it would only be safe to use with arrays that could be passed as `char*` anyway. – David X May 12 '11 at 03:02
2

If it's at all possible to avoid concatenating them, don't. For example if you're going to send them as output, just send one then the other. If you want to concatenate them you need to either get real about using C++ and not treating it like "C with crappy annoying restrictions", or do it the C way which would involve allocating an array of char large enough to hold both strings and copying them into place (preferably with snprintf).

Whichever way you go, if you want to concatenate strings, you have to allocate memory, and you have to be prepared for the possibility that allocation will fail.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
2

Most have mentioned two problems. I'll add a third:

  1. buffer points to const char, so you can't write to it.
  2. buffer is passed by value, so reassigning it won't be visible outside the function.
  3. You have no idea how big buffer is, so if you did write to it, you could cause a buffer overflow.

What you may want (untested) is:

char* functionA(char* buffer, size_t maxlen)
{
    char *message = "hello world";
    if(strlen(buffer) + strlen(message) >= maxlen)
        return NULL;
    return strcat(buffer,message);
}

The length of the two strings must be less then maxlen to allow a nul termination.

strlen and strcat are trivial to implement if you refuse to use them.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
1

I think the answers to Concatenating strings in C, which method is more efficient?, particularly Concatenating strings in C, which method is more efficient?, will have what you're looking for.

But you'll need to change your arguments a bit for sure. You won't be able to change the buffer in that example, since it's declared const.

Community
  • 1
  • 1
Shea Levy
  • 5,237
  • 3
  • 31
  • 42
1

You can find the end position of buffer[] and use that as a destination for a copy of message[]. Any text-book scanning of a string for the terminal '\0' will do, although you want to make sure you don't run off the end of buffer[].

And that reveals a bigger problem. If you have no idea how full buffer is and whether or not your movement of the additional 12 characters (counting the automatically-supplied '\0' on the end) will cause a buffer overflow or not, you need some way to know what the capacity of buffer[ ] is so your code can operate defensively.

Also, although it is safe to make const char *message = ..., the const char *buffer seems a bit odd if you intend to alter it. While the C compiler might not catch that, it is really a violation of the contract implied by using const char *buffer. In addition, a caller is permitted to implement the buffer[ ] in read-only storage although I assume you are the only user of functionA.

So you might want to look at how to change the parameter list and define the interface to this function so it can defend against buffer-over-runs, badly-initialized buffer[ ] strings, etc.

orcmid
  • 2,618
  • 19
  • 20
0

I guess if you know the memory required of the appending message, then we could use memcpy.

somthing like ..

main() { ...

u32 *new_ptr=NULL;
total_len=strlen(previous_msg)+strlen(appending_msg);
new_ptr=malloc(total_len);
memcpy(new_ptr,previous_msg,strlen(previous_msg));
memcpy(new_ptr+strlen(previous_msg), appending_msg, strlen(appending_msg));

... }

The new_ptr will now contain the entire message.

Adit Ya
  • 731
  • 1
  • 8
  • 19
0

Try using strcat(). strcat

Himadri Choudhury
  • 10,217
  • 6
  • 39
  • 47
  • That sounds like a sure formula for buffer overflow or a SEGVIO. – Jim Balter May 12 '11 at 02:43
  • It's not sure to overflow. If the destination buffer is big enough to hold the concatenated string then it should be fine. – Himadri Choudhury May 13 '11 at 13:54
  • Assuming people will ignore your actual statement and understand the hidden meaning behind it is not a good idea for this forum. I just pointed to a function that the user could use to solve their problem, I didn't say that they shouldn't add some error checking/handling code to their implementation. Whenever you deal with C style strings ( which was the basis of the original question ), you have to be careful about overflows. – Himadri Choudhury May 13 '11 at 21:57
0

The whole point of a const char is to be constant -- you're not supposed to modify it. You must place the resulting string in a new buffer, like this:

char* combine (char *new_buffer, const char *buffer, const char *message)
{
    return strcat(strcpy(new_buffer, buffer), message);
}

This copies the string into a new buffer then concatenates the message to it.

Cory Nelson
  • 29,236
  • 5
  • 72
  • 110
0

Once that is done, reassign the buffer pointer to the temporary variable's reference

This will only change what buffer is pointing to inside the function. The pointer you passed into the function call will not be changed.

jjwchoy
  • 1,898
  • 16
  • 20