Copy pointer to pointer in function - C

Pages: 12
Hello,

I'd like to copy pointer to pointer in function and I don't want to use the library. But in main I have the old string instead a new string.

Thanks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


int Insert(char* Str1, char* Str2, int n)
{
	
	stringCopy(Str3, Str1, n);
	stringCopy(Str3, Str2, lenS2);
	stringCopy(Str3, Str1 + n, lenS1 -lenS2);

	Str1 = Str3; // Pointer assignment is OK but in main function, I have old string..

	return 1;
}


int main()
{

	char* Str1 = "Blahblahblah";
	char* Str2 = "123";
	Insert(Str1, Str2, 4);

	printf_s("%s\n", Str1); // I have old string instead new string

	return 0;
}
Line 10 is just overwriting Str1, which is a local variable. If you need to change a pointer in main, you need two levels of indirection to change the pointer within another function.

i.e.
1
2
3
4
5
void foo(type **var)
{
    // ...
    *var = something_else;
}


But I don't understand your code, since I'm not sure what Str3 is or what it's pointing to.

If you're trying to re-implement strcat, just pass a char array buffer and a pointer to a c-string.
Last edited on
Thank you for your answer,
But I can't change the signature of the function.

Str3 is:

char* Str3 = (char*)malloc(lenS1 + lenS2 + 2);
Changing the value of Str1 itself will have no effect outside the local function. It's the same thing as if Str1 were an int. Assigning var = 42; will have no effect outside the local function.

So is Str3 a global variable? That's the only way out of this mess, as you have it. print Str3, not Str1. Otherwise, as you currently have it, what you're doing doesn't make sense to me.

PS, just because I'm bored, I made a modified version of strcat.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>

int my_strlen(const char* str)
{
    int n;
    for (n = 0; *(str++); n++);
    return n;
}

void concat(char* buffer, const char* str, int n)
{
    int len = my_strlen(buffer);
    int append_len = my_strlen(str);
    int i;
    for (i = 0; i < append_len + 1 && i + len < n; i++)
    {
        buffer[i + len] = str[i];
    }
    buffer[n-1] = '\0';
}

int main()
{
    char output[10] = "First";
    concat(output, "Second", 10);

    printf("%s\n", output);

    return 0;
}
Last edited on
how is the return value used? pointers are just integers...
you could return it in the return value, 0 (null in C) for errors etc, as another way out.

then it would just be
newstr = insert(blah blah). I don't think you even have to cast it, in C, do you? I think its friendly to cast it anyway but C people get bent out of shape over unnecessary casting.
Last edited on
just because I'm bored, I made a modified version of strcat.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void strcatn(char* buffer, const char* str, size_t n)
{
	char* end = buffer + n - 1;

	while (*buffer++);

	for (--buffer; buffer < end && (*buffer++ = *str++); );
	*buffer = '\0';
}

int main()
{
	char output[10] = "First";

	strcatn(output, "Second", 10);
	puts(output);

	return 0;
}

Thank you, @Ganado, but your code is wrong.
This is my code, I shouldn't change the signature of Insert method. I want to return Str1 as a new string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<stdio.h>
#include<stdlib.h>

int lengthOfString(char* Str1)
{
	int i, length = 0;
	for (i = 0; Str1[i] != '\0'; i++)
	{
		length++;
	}

	return length;
}

void stringCopy(char* Str3, char* Str1, int x)
{
	int lenStr3 = lengthOfString(Str3);
	int j = 0;
	for (int i = lenStr3; i < lenStr3 + x; i++)
	{
		Str3[i] = Str1[j];
		j++;
	}
	Str3[lenStr3 + x] = '\0';

}

int Insert(char* Str1, char* Str2, int n)
{
	int lenS2 = lengthOfString(Str2);
	int lenS1 = lengthOfString(Str1);

	if (lenS2 == 0 || lenS1 == '\0')
		return -1;
	if (lenS1 < n)
		return -1;
	char* Str3 = (char*)malloc(lenS1 + lenS2 + 2);
	Str3[0] = '\0';
	stringCopy(Str3, Str1, n);
	stringCopy(Str3, Str2, lenS2);
	stringCopy(Str3, Str1 + n, lenS1 - lenS2);

	Str1 = Str3;

	return 1;
}

int main()
{

	char* Str1 = "Blahblahblah";
	char* Str2 = "123";
	Insert(Str1, Str2, 4);

	printf_s("%s\n", Str1);

	return 0;
}
The memory allocated to Str3 is not freed - there's a memory leak.

What is the given desc/spec for insert() - what is it supposed to do?
Thank you @seeplus, but your code doesn't change the output string.

https://i.ibb.co/9sTfL8x/Screenshot-2021-01-29-053344.jpg
Thank you @seeplus,

It's string concatenation at a specific position. for example: Str1 should be "Blah123blahblah" after executing the method.

char* Str1 = "Blahblahblah";
char* Str2 = "123";
Insert(Str1, Str2, 4);
1
2
3
4
5
6
7
8
9
int main()
{
	char output[20] = "blahblahblah";

	strcatn(output, "123", 20);
	puts(output);

	return 0;
}


does.


blahblahblah123


I ask again - what is insert() supposed to do?
OK I understand now.......
1
2
3
char* Str1 = "Blahblahblah";
char* Str2 = "123";
Insert(Str1, Str2, 4); 


That should fail as Str1 doesn't have space for the insertion. You should have:

1
2
char Str1[20] = "blahblahblah";
Insert(Str1, "123", 4, 20);


with the extra param for the size of the buffer.

If you don't then you are changing the address to which Str1 points and expect the calling program to know this and free the memory - which is not good. Instead, rather than insert() returning an int, have it return a char* pointing to the new string.
Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>

void strcatn(char* buffer, const char* str, size_t n)
{
	char* end = buffer + n - 1;

	while (*buffer++);

	for (--buffer; buffer < end && (*buffer++ = *str++); );
	*buffer = '\0';
}

size_t lenstr(const char* str)
{
	const char* beg = str;

	for (; *str; ++str);

	return str - beg;
}

char* insert(const char* str1, const char* str2, size_t n)
{
	size_t l1 = lenstr(str1);
	size_t l2 = lenstr(str2);

	char* buffer = (char*)calloc(l1 + l2 + 1, 1);

	strcatn(buffer, str1, n + 1);
	strcatn(buffer, str2, l2 + n + 1);
	strcatn(buffer, str1 + n, l1 + l2 + 1);
	return buffer;
}

int main()
{
	const char* const str1 = "blahblahblah";

	char* out = insert(str1, "123", 4);

	puts(out);
	free(out);

	return 0;
}



blah123blahblah


Thank you @seeplus, but I shouldn't change the signature of method.

int Insert(char* Str1, char* Str2, int n)
The address pointed to by Str1 can't be changed by Insert(). As you are not passing as an argument the size of the Str1 buffer, this means that it has to be assumed that the memory pointed to by Str1 is large enough to contain the final string - which is dangerous for buffer overflow issues.

Who devised this function definition - it's bad design!
Consider then (not good - potential buffer overflow!):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>

void strcatn(char* buffer, const char* str, size_t n)
{
	char* end = buffer + n - 1;

	while (*buffer++);

	for (--buffer; buffer < end && (*buffer++ = *str++); );
	*buffer = '\0';
}

size_t lenstr(const char* str)
{
	const char* beg = str;

	for (; *str; ++str);

	return str - beg;
}

int insert(char* str1, const char* str2, size_t n)
{
	size_t l1 = lenstr(str1);
	size_t l2 = lenstr(str2);

	if (l2 == 0 || l1 == 0 || l1 < n)
		return -1;

	char* buffer = (char*)calloc(l1 + l2 + 1, 1);

	strcatn(buffer, str1, n + 1);
	strcatn(buffer, str2, l2 + n + 1);
	strcatn(buffer, str1 + n, l1 + l2 + 1);
	*str1 = 0;
	strcatn(str1, buffer, l1 + l2 + 1);

	free(buffer);
	return 1;
}

int main()
{
	char str1[20] = "blahblahblah";

	insert(str1, "123", 4);
	puts(str1);

	return 0;
}

Last edited on
For a version not using strcatn, consider (with the same caveats):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
size_t lenstr(const char* str)
{
	const char* beg = str;

	for (; *str; ++str);

	return str - beg;
}

int insert(char* str1, const char* str2, size_t n)
{
	size_t l1 = lenstr(str1), l2 = lenstr(str2);

	if (l2 == 0 || l1 == 0 || l1 < n)
		return -1;

	char *buffer = (char*)calloc(l1 + l2 + 1, 1), *bufbeg = buffer, *org = str1;

	for (size_t i = 0; i < n && (*buffer++ = *str1++); ++i);
	while (*buffer++ = *str2++);
	for (--buffer; *buffer++ = *str1++; );
	for (str1 = org, buffer = bufbeg; *str1++ = *buffer++; );

	free(bufbeg);
	return 1;
}

Ah right, this whole time I wasn't considering making str1 itself point to an actual buffer and not just read-only memory. That would work and I think meet OP's reqs.

Edit:
Thank you, @Ganado, but your code is wrong.
Maybe English isn't your first language, so you are speaking incorrectly. My code being "wrong" means something different than my code not meeting your specific needs. If my code is wrong, tell me how it's wrong. The buffer being size 10 was intentional as a test.
Last edited on
Pages: 12