What are the issues with this code for reversing a string in memory?

In summary: This code does the same thing as the previous code, but it uses a variable to keep track of where it is in the reversed string. Since bufsize is a power of two, it can simply use i as an offset into the string. This also makes the code easier to read.
  • #1
James889
192
1
Hi,

I'm trying to write a simple program for reversing a string stored in memory.

This is what I've come up with. For some reason this code coredumps, so something is wrong.
any ideas ?

Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *reverse(char *buf,unsigned int bufsize ){

        /* Allocate memory for the reversed string */
        char *ptr = (char *)malloc(bufsize);

        /* Get the address of the last character in the buffer. */
        int buffaddr = &buf[bufsize];
        char *buffptr = (char *)buffaddr;

               *ptr++ = *buffptr--;
return ptr;
}


int main(void){

        char Buffer[100];

        strcpy(Buffer,"a cup of coffee");

        char *reversed = reverse(Buffer,sizeof(Buffer));

free(*reversed);

return 0;
}
 
Technology news on Phys.org
  • #2
Don't you need a while loop in the reverse function to iterate over the string?

Also you could have simply added the bufsize to your buffptr to get the end of the buffer.

The real problem is that your string lengths are variable and you need to start copying at the end of the string not the end of the buffer.

The core dump is due to your buffptr pointing past the end of the buffer. Your buffer goes from 0 to 99 but you referenced 100.
 
  • #3
Still, your program won't work.
For example, dynamic memory allocation with new operator (for explanation purpose). I don't know how to explain this with malloc (my teacher started the pointer section since early last week :biggrin: ).
PHP:
char* a=new char;
char* a=new char[10];
they only differ in array of chars being allocated. In your program, this similar "a" pointer is initialized to nothing and therefore
PHP:
*a++=*b--;
won't copy anything into a. But if you do this
PHP:
a[i]=*b--;i++;
it will work. Because "a" then knows where it is going to assign the value to.
And finally your while loop may look like this
PHP:
while (*buffptr)
	{
		ptr[i] = *buffptr--;	
		i++;
	}
Don't forget to assign the last character bit of this string to '\0'. And your good question is very tricky.
 
  • #4
James889 said:
I'm trying to write a simple program for reversing a string stored in memory.
That problem statement seems to imply that the goal is to reverse a string in place as opposed to making a reversed copy of that string. This can be done via indexing or via pointers.
 
  • #5
One thing i don't understand.
The statement 'char **bufptr = buf' and putchar(bufptr) whould print out the same output as putchar(buf). But it doesn't. Why?

Code:
char *reverse(char *buf){

        /* Allocate memory for the reversed string */
        char *ptr = (char *)malloc(100);

        char **bufptr = buf;

        /* This should return the same output as putchar(buf), but doesn't. Why? */
        putchar(bufptr);
        }
 
  • #6
With pointers, a char** is a pointer to a pointer of a character array while char* is a pointer to the starting offset of a character array.

If you are returning the pointer to the offset of a character array then you are returning a char* (which should be valid, allocated, and point to the right thing).

The typical reason for using double pointers (like char**) is that you pass it so that you can modify a variable in the scope of a function and have it stay that way after the function terminates. Outside of this kind of application, it makes no sense to use double pointers for most purposes.

Also you need to return a pointer to some character array and your function doesn't seem to do this.
 
  • #7
So why do i get different results from *buf and **bufptr ?
 
  • #8
James889 said:
Code:
    char *reversed = reverse(Buffer,sizeof(Buffer));
    free(*reversed);
The core dump probably occurs on the free. It should be free(reversed), without the *, but another issue is that reverse() allocates memory in ptr, but returns an incremented copy of ptr, so that will also cause free() to fail.

Code:
char *reverse(char *buf){
        char *ptr = (char *)malloc(100);
        char **bufptr = buf;

You could set bufptr to point to the address the local copy (on the stack) of buf. Somewhat useless but it would work:

Code:
char *reverse(char *buf){
        char *ptr = (char *)malloc(100);
        char **bufptr = &buf;
/* ... after this, then (*bufptr)[i] refers to the same location as buf[i]; */

Assuming this isn't homework, then here is an alternative:

Code:
void reverse(char * buf, int bufsize)
{
int mid = bufsize/2;
int i;
char c;
    for(i = 0; i < mid; i++){
        c = buf[i];
        buf[i] = buf[bufsize-i-1];
        buf[bufsize-i-1] = c;
    }
}
 
Last edited:
  • #9
chiro said:
With pointers, a char** is a pointer to a pointer of a character array
No, you're off in the levels of indirection. char** is a pointer to a pointer to a character.
chiro said:
while char* is a pointer to the starting offset of a character array.
Strictly speaking, char* is a pointer to a char. That character might or might not be in an array of characters. If the character happens to be in an array, it could be any character in the array, not necessarily the beginning character.
chiro said:
If you are returning the pointer to the offset of a character array then you are returning a char* (which should be valid, allocated, and point to the right thing).

The typical reason for using double pointers (like char**) is that you pass it so that you can modify a variable in the scope of a function and have it stay that way after the function terminates. Outside of this kind of application, it makes no sense to use double pointers for most purposes.

Also you need to return a pointer to some character array and your function doesn't seem to do this.
 
  • #10
Multiple problems with the originally posted code.

James889 said:
Code:
char *reverse(char *buf,unsigned int bufsize )

What is the meaning of the bufsize variable? The length of the original buffer (1), or the length of the original string (2)? Or the length of the buffer to allocate (3)? Of all these, only (2) would be really useful to reverse(). (1) gives to reverse() insufficient information, so it will still have to find out the length of the original string. (3) is even worse, because the length of the string still needs to be found, and it may so happen that it is greater than the size of the buffer to allocate - what is reverse() to do in such a situation?

Code:
        int buffaddr = &buf[bufsize];

Regardless of the (1), (2) & (3) options above, this is simply wrong, because (A) the address obtained by the right-hand side is not of the int type; and (B) the address of the buf[bufsize] in cases (1) & (3) points just after the end of the buffer; in case (2), it points to the terminating zero character, which may or may not be wrong. (A) can easily result in a bogus address being eventually assigned to buffptr in the next line. In short, do not do it: there is simply no reason to convert the address to int in this case. To address problem (B), you need to obtain the true length of the string.

Code:
               *ptr++ = *buffptr--;

This line is meaningless. In case (2), it will copy just the terminating zero character; in cases (1) and (3) it will, at best, copy some random garbage character; or it can dereference an invalid address location and make your program go boom.

Code:
return ptr;

Bad, too, because it returns not the address of the allocated buffer, but the address somewhere (hopefully) in this buffer.

Code:
free(*reversed);

*reversed is a character, whose numeric value is between 0 and 255, inclusively. This is then converted to an address, which free() expects. This address will be within the first 256 bytes of the process's address space. On most modern operating systems, such an address is invalid.

What you want to do is free(reversed) - assuming you deal with all the other problems.
 
  • #11
voko said:
Multiple problems with the originally posted code.
What is the meaning of the bufsize variable? The length of the original buffer (1), or the length of the original string (2)? Or the length of the buffer to allocate (3)? Of all these, only (2) would be really useful to reverse(). (1) gives to reverse() insufficient information, so it will still have to find out the length of the original string. (3) is even worse, because the length of the string still needs to be found, and it may so happen that it is greater than the size of the buffer to allocate - what is reverse() to do in such a situation?
Regardless of the (1), (2) & (3) options above, this is simply wrong, because (A) the address obtained by the right-hand side is not of the int type; and (B) the address of the buf[bufsize] in cases (1) & (3) points just after the end of the buffer; in case (2), it points to the terminating zero character, which may or may not be wrong. (A) can easily result in a bogus address being eventually assigned to buffptr in the next line. In short, do not do it: there is simply no reason to convert the address to int in this case. To address problem (B), you need to obtain the true length of the string.
This line is meaningless. In case (2), it will copy just the terminating zero character; in cases (1) and (3) it will, at best, copy some random garbage character; or it can dereference an invalid address location and make your program go boom.
Bad, too, because it returns not the address of the allocated buffer, but the address somewhere (hopefully) in this buffer.
*reversed is a character, whose numeric value is between 0 and 255, inclusively. This is then converted to an address, which free() expects. This address will be within the first 256 bytes of the process's address space. On most modern operating systems, such an address is invalid.

What you want to do is free(reversed) - assuming you deal with all the other problems.
Code:
void reverse(char *buf){

unsigned int strlen = 0;
  /* Allocate memory for the reversed string */
  char *ptr;
  ptr = (char *)malloc(100);
 

/* Find the length of the string in the buffer */
  while( *buf++ != '\0'){
  strlen++;
  }
/* Copy */
for(strlen;strlen>0;strlen--){
  *ptr++ = *buf--;
}}

Could you do something similar to this?
 
  • #12
Code:
  ptr = (char *)malloc(100);

Bad. This must be the real size required for the string, not some constant.

Code:
/* Find the length of the string in the buffer */
  while( *buf++ != '\0'){
  strlen++;
  }

OK, but why not use strlen()?

Code:
/* Copy */
for(strlen;strlen>0;strlen--){
  *ptr++ = *buf--;
}

Bad.

1. When the loop starts, buf points just after the end of the original string, not even at its zero terminator.

2. There is no code that will zero-terminate the new string.

3. And I do not see that the new string is returned.
 
  • #13
If you want to returned a reversed copy of the input string, try this:

Code:
char * reverse(char * buf)
{
int buflen = 1;
char * src;
char * dst;
char * rtn;
    if(!buf)
        return(0);
    src = buf;
    while(*src++)
        buflen++;
    dst = rtn = malloc(buflen);
    src--;
    while(src != buf)
        *dst++ = *--src;
    *dst = 0;
    return(rtn);
}
 
Last edited:
  • #14
rcgldr said:
If you want to returned a reversed copy of the input string, try this:

Code:
char * reverse(char * buf)
{
int buflen = 1;
char * src;
char * dst;
char * rtn;
    if(!buf)
        return(0);
    src = buf;
    while(*src++)
        buflen++;
    dst = rtn = malloc(buflen);
    src--;
    while(src != buf)
        *dst++ = *--src;
    *dst = 0;
    return(rtn);
}
Based on what's in the OP...
James889 said:
I'm trying to write a simple program for reversing a string stored in memory.
... I don't believe that the goal is to return a reversed copy of the input string, but instead to actually reverse the input string. The usual way of doing this is to use a loop that swaps the first and last nonnull character, then swaps the second and the next to last, and so on until you get to the middle of the string. You definitely don't want to be swapping characters after you get to the middle, or you undo all the previous swaps.
 
  • #15
Mark44 said:
Based on what's in the OP...
... I don't believe that the goal is to return a reversed copy of the input string, but instead to actually reverse the input string.
Which I already posted an example of back in post #8, but the thread kept going.
 
  • #16
Ok, so after a bit of fiddling i finally managed to come up with a version that works(not saying anything about code quality etc ;) )
Code:
char *reverse(char *buf){

  /* Allocate enough memory for the string */
  int length = strlen(buf);
  char *ptr = calloc(length,sizeof(char));
  char **p2p;
  p2p = ptr;

  /* Null terminate the string */
  *(ptr+length) = '\0';

  for(int i=length-1;i>=0;i--){

  *( ptr + i ) = *buf++;
  }  return p2p;

}
 
  • Like
Likes Medicol
  • #17
James889 said:
Ok, so after a bit of fiddling i finally managed to come up with a version that works(not saying anything about code quality etc ;) )
Code:
char *reverse(char *buf){

  /* Allocate enough memory for the string */
  int length = strlen(buf);
  char *ptr = calloc(length,sizeof(char));
  char **p2p;
  p2p = ptr;

  /* Null terminate the string */
  *(ptr+length) = '\0';

  for(int i=length-1;i>=0;i--){

  *( ptr + i ) = *buf++;
  }  return p2p;

}
The main problems I see are the following.
1. p2p is declared as type char ** (i.e., pointer to a pointer to a char). In the line following the declaration, you set p2p to ptr. Since ptr is of type char * and p2p is of type char **, you have different levels of indirection. Your compiler should at least have generated a warning about this.
2. ptr is initialized with the value returned by calloc(), which is the address of a block of length bytes. This memory can be treated as if it were an array, with indexes running from 0 through length - 1. A few lines later you put a null character at index length. IOW, you are setting memory that doesn't belong to the array, which is not a good thing to do.

In the OP you said this:
I'm trying to write a simple program for reversing a string stored in memory.
Your buf parameter contains the address of a string already stored in memory. Why don't you reverse that string rather than make a reversed copy of the string?
 

What is "C reverse string in memory"?

"C reverse string in memory" is a programming technique used to reverse the order of characters in a string within the computer's memory. This is commonly used in the C programming language, hence the name.

Why is "C reverse string in memory" important?

Reversing a string in memory can be useful in situations where the original string needs to be modified without creating a new string variable. It is also a common coding challenge used to test a programmer's ability to manipulate data in memory.

How does "C reverse string in memory" work?

The technique involves using a pointer to iterate through the string and swapping the characters at either end of the string until the entire string has been reversed. This can be done using a loop or a recursive function.

Is "C reverse string in memory" a difficult concept to understand?

It can be difficult for beginners to understand, but with practice and understanding of pointers and memory management, it can become easier. There are also many resources and examples available online to help with understanding this concept.

Are there any potential issues or limitations with using "C reverse string in memory"?

One potential issue is that the string being reversed must be modifiable, as the technique involves swapping characters in place. This may not be possible with certain data structures or string literals. Additionally, using this technique may impact the performance of the program, so it should be used carefully in time-critical applications.

Similar threads

  • Programming and Computer Science
Replies
7
Views
1K
  • Programming and Computer Science
4
Replies
118
Views
6K
  • Programming and Computer Science
Replies
13
Views
2K
  • Programming and Computer Science
Replies
5
Views
886
  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
Replies
4
Views
3K
  • Programming and Computer Science
Replies
6
Views
2K
  • Programming and Computer Science
Replies
14
Views
4K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
949
  • Programming and Computer Science
Replies
23
Views
1K
Back
Top