1

I'm trying to concatenate another string onto arg[0].

#include <stdio.h>
#include <string.h>

int main() {

    char* arg[] = {
        "Hello",
        NULL,
        NULL,
        NULL
    };

    strcat(arg[0], " World");

}

This returns abort trap.

What am I doing wrong?

Carol Ward
  • 699
  • 4
  • 17
  • 3
    You need to create a new character buffer big enough to hold `Hello` + your new string and then concatenate them into that new buffer. – Gillespie Feb 14 '20 at 15:02
  • 3
    not allocating enough space for the concatenation. – yano Feb 14 '20 at 15:02
  • 1
    " World" have 6 (becarful you have space at the begining) character and "Hello" only 5 (Total = 11 character !). – Landstalker Feb 14 '20 at 15:03
  • 1
    More precisely, `arg[0]` can only hold 5 characters (not counting null terminator) and you are trying to stuff 11 characters into it. – Gillespie Feb 14 '20 at 15:04
  • 3
    @Gillespie The number of characters is not the issue. String literals are read-only, so writing any number of characters is an error. – interjay Feb 14 '20 at 15:05
  • 1
    Does this answer your question? [Why do I get a segmentation fault when writing to a string initialized with "char \*s" but not "char s\[\]"?](https://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-string-initialized-with-cha) – Sander De Dycker Feb 14 '20 at 15:07
  • Since string literals are read-only, is there a way to make it write as well? Are strings always read-only? – Carol Ward Feb 14 '20 at 15:07
  • 1
    True, but she will encounter the same problem if she tries to concatenate something to `char str[] = "hello"` as well. I was trying not to delve too far into technicalities – Gillespie Feb 14 '20 at 15:07
  • 1
    Also refer to [What is the difference between char s\[\] and char *s?](https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s) – Sander De Dycker Feb 14 '20 at 15:07
  • 1
    https://stackoverflow.com/a/1088667/3476780 – yano Feb 14 '20 at 15:09
  • 1
    And more specifically : [How do I concatenate const/literal strings in C?](https://stackoverflow.com/questions/308695/how-do-i-concatenate-const-literal-strings-in-c) – Sander De Dycker Feb 14 '20 at 15:11
  • 1
    It's almost always better to use strncat than strcat. Also, you might read http://stromberg.dnsalias.org/~strombrg/checking-early.html for an exploration of what can go wrong when you reference undefined memory - it uses FORTRAN for its examples, but the same thing applies to C. – dstromberg Feb 14 '20 at 15:18
  • 1
    ...but don't blindly apply @dstromberg 's good advice to `strncpy()` over `strcpy()`, because `strncpy()` behaviour is not quite what you'd naively expect both before *and* after reaching the size limit. – DevSolar Feb 14 '20 at 15:24

2 Answers2

2

You are trying to rewrite a string literal with:

char* arg[] = { "Hello", ..... };    // "Hello" is a string literal, pointed to by "arg[0]".

strcat(arg[0], " World");       // Attempt to rewrite/modify a string literal.

which isn´t possible.

String literals are only available to read, but not to write. That´s what make them "literal".


If you wonder about why:

char* arg[] = { "Hello", ..... }; 

implies "Hello" as a string literal, You should read the answers to that question:

What is the difference between char s[] and char *s?


By the way, it would be even not possible (or at least get a segmentation fault at run-time) if you would do something like that:

#include <stdio.h>
#include <string.h>

int main() {

    char a[] = "Hello";  // 6 for holding "Hello" (5) + "\0" (1). 

    strcat(a, " World");   

}

because the array a needs to have 12 characters for concatenating both strings and using strcat(a, " World"); - "Hello" (5 characters) + " World" (6 characters) + \0 (1 character) but it only has 6 characters for holding "Hello" + \0. There is no memory space added to the array automagically when using strcat().

If you execute the program with these statements, you are writing beyond the bounds of the array which is Undefined Behavior and this will get you probably prompt a Segmentation Fault error.

1

One of the shortcomings of C strings is that you need to know how big they will be ahead of time.

#include <stdio.h>
#include <string.h>

int main() {
    char arg[1024] = "Hello";
    strcat(arg, " World");
    printf("%s\n", arg);
}

In this case, the size of the concatenated string must be less than 1024 characters. This is why it is safer to use something like C++, where you have std::string to prevent these types of issues.

Gillespie
  • 5,780
  • 3
  • 32
  • 54
  • I think changing to a whole another language is a bit out of scope and C++ introduces so many other pitfalls and complexities. – ljrk Feb 15 '20 at 09:54
  • C++ isn't exactly a "whole other language" though. The above snippet is valid C++. There's really no reason to use pure C in this day and age outside of the context of academia when you have much safer alternatives like Rust and C++. – Gillespie Feb 16 '20 at 00:04
  • 1
    it is valid but bad C, eg. it is missing `void` in the function declaration. And yes, C++ is a whole new language, if one disregards the factually wrong claims by Bjarne for once. There are quite a few differences and good reasons not to use some C++ features but rather improve C in details. If one would go safe, I'd neither choose C nor C++, but this question is tagged C, so the answers should be C. – ljrk Feb 16 '20 at 09:41