Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C function change string using pointer

Tags:

c

function

string

I'm trying to make a function that changes a char array from the main function, that's what I'm trying to do:

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

void change(char *a);

int main()
{
    char a[] = "hello";
    printf("\na = %s", a);
    change(a);
    printf("%\na = %s", a);
    getch();
}

void change(char *a)
{
    a = "goodbye";
}
like image 863
GustavoKnx Avatar asked Dec 19 '22 11:12

GustavoKnx


2 Answers

Several problems with this code, but first we need to take a step back and talk about how arrays are handled in C.

Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

In the declaration

char a[] = "hello";

"hello" is a string literal, which has type "6-element array of char" (5 characters plus the 0 terminator). Since it is being used to initialize the array a in a declaration, the rule above doesn't apply; instead, the size of a is set to be the same as the size of the literal (6), and the contents of the string literal are copied to the array.

When you call change from main as

change(a);

the expression a has type "6-element array of char". Since it is neither a string literal nor the operand of the sizeof or unary & operators, that expression will be converted to type "pointer to char", and the value of the expression will be the address of the first element of the aray. Hence why the change function is declared as

void change(char *a);

In this context, a is simply a pointer. When you write

a = "goodbye";

the string literal "goodbye" is not being used in an initializer, and it's not the operand of the sizeof or unary & operators, so the expression is converted to type "pointer to char", and the value of the expression is the address of the first character. So what happens here is that you're copying the address of the string literal "goodbye" to a. This overwrites the value in a, but this a is not the same object in memory as the array a in main, so any changes to it are not reflected in main.

If you want to update the contents of an array, you will need to use the library functions strcpy/strncpy (for 0-terminated strings) or memcpy (for everything else), or update each element explicitly (a[0]='g'; a[1]='o'; a[2]='o';, etc).

To update the contents of a, you'd use

strcpy( a, "goodbye" );

Except...

a is only large enough to hold 5 characters plus a 0 terminator; "goodbye" is 7 characters plus the 0 terminator; it's two characters larger than what a is capable of storing. C will happliy let you perform the operation and trash the bytes immediately following a, which may lead to any number of problems (buffer overruns such as this are a classic malware exploit). You have a couple of choices at this juncture:

First, you could declare a to be large enough to handle either string:

#define MAX_LEN 10
...
char a[MAX_LEN] = "hello";

Second, you could limit the size of the string copied to a:

void change( char *a, size_t size )
{
  strncpy( a, "goodbye", size - 1 );
  a[size - 1] = 0;
}

Note that you will need to pass the number of elements a can store as a separate parameter when you call change; there's no way to tell from a pointer how big the array it points to is:

change( a, sizeof a / sizeof *a ); // although in this case, sizeof a would be
                                   // sufficient.
like image 197
John Bode Avatar answered Dec 24 '22 03:12

John Bode


The main problem is that you are sending a copy of the char pointer a by doing this:

void change(char *a)
{
    a = "goodbye";
}

if you want to change a value in another function you should do this:

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

void change(char **a);

int main()
{
    char *a = "hello";
    printf("\na = %s", a);
    change(&a);
    printf("%\na = %s", a);
    getch();
}

void change(char **a)
{
    *a = "goodbye";
}
like image 27
CollioTV Avatar answered Dec 24 '22 03:12

CollioTV