The issue you are having is that string2
does not have memory allocated to it.
Your code is missing some details, but I'll assume it looks something like this:
#include <stdio.h>
int main()
{
char *originalStr = "Hello NewArsenic";
char *newStr;
// YMMV depending on the compiler for this line. Might print (null) for
// newStr or it might throw an error.
printf("Original: %s\nNew: %s\n", originalStr, newStr);
int i;
for (i = 0; *(originalStr + i) != '\0'; i++)
{
*(newStr + i) = *(originalStr + i);
}
printf("Original: %s\nNew: %s\n", originalStr, newStr);
return 0;
}
TL;DR Your Issue
Your issue here is that you are attempting to store some values into newStr
without having the memory to do so.
Solution
Use malloc
.
#include <stdio.h>
#include <stdlib.h> // malloc(size_t) is in stdlib.h
#include <string.h> // strlen(const char *) is in string.h
int main()
{
char *originalStr = "Hello NewArsenic";
// Note here that size_t is preferable to int for length.
// Generally you want to be using size_t if you are working with size/length.
// More info at https://stackoverflow.com/questions/19732319/difference-between-size-t-and-unsigned-int
size_t originalLength = strlen(originalStr);
// This is malloc's typical usage, where we are asking from the system to
// give us originalLength + 1 many chars.
// The `char` here is redundant, actually, since sizeof(char) is defined to
// be one by the C spec, but you might find it useful to see the typical
// usage of `malloc`.
// Since malloc returns a void *, we need to cast that to a char *.
char *newStr = (char *)malloc((originalLength + 1) * sizeof(char));
// Your code stays the same.
printf("Original: %s\nNew: %s\n", originalStr, newStr);
size_t i;
for (i = 0; *(originalStr + i) != '\0'; i++)
{
*(newStr + i) = *(originalStr + i);
}
// Don't forget to append a null character like I did before editing!
*(newStr + originalLength) = 0;
printf("Original: %s\nNew: %s\n", originalStr, newStr);
// Because `malloc` gives us memory on the stack, we need to tell the system
// that we want to free it before exiting.
free(newStr);
return 0;
}
The long answer
What is a C String?
In C, a string is merely an array of characters. What this means is that for each character you want to have have, you need to allocate memory.
Memory
In C, there are two types of memory allocation - stack- and heap-based.
Stack Memory
You're probably more familiar with stack-based memory than you think. Whenever you declare a variable, you're defining it on the stack. Arrays declared with bracket notation type array[size_t]
are stack-based too. What's specific about stack-based memory allocation is that when you allocate memory, it will only last for as long as the function in which it was declared, as you're probably familiar with. This means that you don't have to worry about your memory sticking around for longer than it should.
Heap Memory
Now heap-based memory allocation is different in the sense that it will persist until it is cleared. This is advantageous in one way:
- You can keep values of which you don't know the size at compile time.
But, that comes at a cost:
- The heap is slower
- You have to manually clear your memory once you're done with it.
For more info, check out this thread.
We typically use the function (void *) malloc(size_t)
and its sister (void *) calloc(size_t, size_t)
for allocating heap memory. To free the memory that we asked for from the system, use free(void *)
.
Alternatives
You could've also used newStr = originalStr
, but that would not actually copy the string, but only make newStr
point to originalStr
, which I'm sure you're aware of.
Other remarks
- Generally, it's an anti-pattern to do:
char* string = "literal";
This is an anti-pattern because literals cannot be edited and shouldn't be. Do:
char const* string = "literal";
See this thread for more info.
- Avoid using
int
in your loop. Use size_t
See this thread.