1

I'm learning c and performing some exercise with strings, functions and pointers. The exercise is to take a string into a function, make an elaboration and give a result out. The function 'LenCorr' add 'i' letters to the end of input string to achieve 8 chars lenght.

My code is:

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

#define StrLen 100

char * LenCorr(char * str);

void main(void)
{
    char t1[StrLen] = "Hello3"; // this is the input string
    printf("Input : %s\n", t1);  
    
    char *t3 = LenCorr(t1);     // pass through the 'LenCorr' function to t3 pointer to char array
    printf("LenCorr p: %p\n", t3); // then I print the pointer ...
    printf("LenCorr s: %s\n", t3); // ... but the content is empty
}

char * LenCorr(char * str)
{
    char si[StrLen]; // I create various strings
    char su[StrLen];
    char st[StrLen] = "iiiiiiiiiiiiiiiiiii";
    
    strcpy(si,str); // I have to copy the 'str' input to the local string

    // here I perform some elaborations
    int ln = strlen(si);
    int ct = 8 - ln;
    
    if (ln < 8) {strncat(si, st, ct);}

    // ... and the final result is correct into 'si' string
    strcpy(su,si); // that I copy into a 'su' string (another)

    char * output = su;
    
    printf("Debug output: %s\n", output); // here I see the result of string elaboration 
    printf("Debug output pointer: %p\n", output); // here I get a pointer of the string elaboration

    return output;
}

But at the end the function returns the proper pointer value but the value is 0. Here the console output:

Input : Hello3
Debug output: Hello3hh
Debug output ptr: 0x7fff4cf17c30
LenCorr p: 0x7fff4cf17c30
LenCorr s: 

Why ?

Naccio
  • 31
  • 7
  • `si`, `su`, and `st` only live for the duration of the `LenCorr` function - after that point they go out of scope and are destroyed. Reading a pointer to that memory (`output`, `t3`) is Undefined Behavior. – 0x5453 Jul 27 '21 at 21:35
  • `su` is a local variable. Local variables are only valid within the function and accessing references to them outside the function is Undefined Behaviour. – kaylum Jul 27 '21 at 21:35
  • Does this answer your question? [How to access a local variable from a different function using pointers?](https://stackoverflow.com/questions/4570366/how-to-access-a-local-variable-from-a-different-function-using-pointers) – kaylum Jul 27 '21 at 21:36
  • as they mentioned above, you would need to allocate space on the heap so that when the function ends the variable will not be destroyed. Of course you would need to ```free()``` this variable before terminating the program. Instead of setting output = su... ```char * output = malloc(strlen(su) * sizeof(char)); strncpy(output, su, strlen(su));``` – NeonFire Jul 27 '21 at 21:40
  • Ok, seem that in c is more elegant if I don't return arrays and strings as return of a function, but better to use a pointer to the target variable as argument. In my example became: `LenCorr(char * ret,char * str)` where ret is the argument that point to return variable. – Naccio Jul 28 '21 at 19:19

3 Answers3

0

As I mentioned in a comment you just need to allocate space on the heap using malloc so that it is not destroyed when the function ends (pops off the stack). Just make sure to use free() at the end of your main.

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

#define StrLen 100

char * LenCorr(char * str);

int main(void)
{
  char t1[StrLen] = "Hello3\0";
  printf("Input : %s\n", t1);  
  
  char *t3 = LenCorr(t1);
  printf("LenCorr p: %p\n", t3); 
  printf("LenCorr s: %s\n", t3); 
  free(t3);
}

char * LenCorr(char * str)
{
  char si[StrLen];
  char st[StrLen] = "iiiiiiiiiiiiiiiiiii\0";
  strncpy(si,str, strlen(str));
  int ln = strlen(si);
  int ct = 8 - ln;
  
  if (ln < 8) { strncat(si, st, ct); }
  char * output = malloc(strlen(si) * sizeof(char)); //heap-allocation
  strncpy(output, si, strlen(si));
  
  printf("Debug output: %s\n", output);
  printf("Debug output pointer: %p\n", output);
  
  return output;
}

NeonFire
  • 186
  • 2
  • 7
0

A char array lifetime is confined to the scope where it's declared, as soon as the function execution ends it's no longer legal to access the local array.

That is exactly what happens here, output will be pointing to an invalid memory location when it's returned, later accessing this memory location as you do in main amounts to undefined behavior.

The idiomatic way to do this is to pass a pointer to the buffer, where you want to store the string, as an argument of the function:

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

#define StrLen 100

void LenCorr(char *str, char* output); // passing a pointer to the destination bufffer
void main(void)
{
    char t1[StrLen] = "Hello3";

    char t3[StrLen]; // destination buffer

    printf("Input : %s\n", t1);  
    
    LenCorr(t1, t3); // pass destination buffer as argument

    printf("LenCorr p: %p\n", t3); 
    printf("LenCorr s: %s\n", t3);
}
void LenCorr(char * str, char *output)
{
    char si[StrLen]; 
    char su[StrLen];
    char st[StrLen] = "iiiiiiiiiiiiiiiiiii";
    
    strcpy(si,str); 

    int ln = strlen(si);
    int ct = 8 - ln;
    
    if (ln < 8) {strncat(si, st, ct);}

    strcpy(su, si); 

    strcpy(output, su); // copy string to its final destination
    
    printf("Debug output: %s\n", output);
    printf("Debug output pointer: %p\n", output);
}
anastaciu
  • 23,467
  • 7
  • 28
  • 53
0

I think that, in c, it is more usefull to not use return arrays and strings from functions, but it is better to use a pointer to the target variable as an argument. In the example, the function should became like in this definiton:

LenCorr(char * ret, char * str)

where 'ret' is the argument that point to return variable.

The complete code becames:

void main(void)
{
    char t1[StrLen] = "Hello3"; // this is the input string
    char t3[StrLen]
    printf("Input : %s\n", t1);  
    
    LenCorr(t3, t1);     // pass through the 'LenCorr' function to t3 pointer to char array
    printf("LenCorr p: %p\n", t3); // then I print the pointer ...
    printf("LenCorr s: %s\n", t3); // ... but the content is empty
}

int LenCorr(char * ret, char * str)
{
    char si[StrLen];
    
    strcpy(si, str);
    
    //.... various code ....

    strcpy(ret, si);
}
Naccio
  • 31
  • 7