I just started learning C and I'm quite unsure of how to "correctly" access and edit values of a character pointer.
For example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* text = malloc(20);
char* othertext = "Teststring";
do
{
*text++ = *othertext++;
} while (*othertext != '\0');
printf("%s\n", text + 3);
free(text);
return 0;
}
Firstly, why does the do-while function not work? The content of "othertext" doesn't get copied to the "text" pointer. Furthermore, the program crashes when free(text) is being executed!
We know that this code works if we add a second pointer:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* text = malloc(20);
char* othertext = "Teststring";
char *ptr1 = text;
char *ptr2 = othertext;
do
{
*ptr1++ = *ptr2++;
} while (*ptr2 != '\0');
printf("%s\n", text + 3);
free(text);
return 0;
}
But both pointers have basically the same address! They have the same values in the debugger, so how does a second pointer make any difference?
As a final note: We are not allowed to use string.h. And we do know there's a subtle difference between arrays and pointers. But we need to specifically understand how char* works!
You should pass to free() the pointer returned by malloc() (the same address). You are passing the incremented pointer i.e. the text pointer now doesn't have the address of the pointer returned by malloc() instead it's an the address of the last element of text, use another pointer to copy the data, or better an index
size_t i;
for (i = 0 ; othertext[i] != '\0' ; ++i)
text[i] = othertext[i];
text[i] = '\0';
You say
But both pointers have basically the same address!
This is not true, try this
printf("%p -- %p\n", (void *) text, (void *) ptr1);
You modify the value of the text pointer in your loop, such that at the end it's not pointing to the beginning of the memory region you allocated; that's (part of) why you don't see the text, and why the free crashes.
You need to preserve that original pointer value (which you do in your second snippet).
You are actually changing the address that text is pointing too.
Consider a very simple memory in which text points to address 5 and othertext points to address 42 on which the T of TestString has been placed.
You now copy the character found at address 42 to address 5, so that address 5 also contains a T. However, you now increment the address that text is pointing too. In other words, text now points at address 6. You also increment othertext which now points to address 43.
In the next round you copy the e found at address 43 to address 6 and increment both again. This is all fine.
However after you are done copying text will point to 5 + 10 = 15. On address 15 however you can not print anything, nor can you remove what is there.
In your second piece of code there are no problems because text keeps pointing to address 5.
do this printf inside the loop after the assignment line. I think you will see why it's not working ;)
printf("%s\n", text);
Related
My understanding:
char * c means c is pointing nothing.
When I type "Hello World", c is now pointing the first address of "Hello World".
It should print H and e, but I got "Segmentation fault: 11" error.
Can anyone please enlighten me why and how char * c = NULL; is causing an error?
Thanks in advance!
#include <stdio.h>
int main(void)
{
char * c = NULL;
gets(c);
printf("%c, %c\n", c[0], c[1]);
return 0;
}
gets doesn't allocate memory. Your pointer is pointing to NULL, which cannot be written to, so when gets tries to write the first character there, you seg fault.
The solution is:
Use a stack or global array (char c[1000];) or a pointer to dynamically allocated memory (char *c = malloc(1000);), not a NULL pointer.
Never use gets, which is intrinsically broken/insecure (it can't limit the read to match the size of the available buffer); use fgets instead.
char *c = NULL; declares the pointer c initialized to NULL. It is a pointer to nowhere.
Recall, A pointer is just a variable that holds the address to something else as its value. Where you normally think of a variable holding an immediate values, such as int a = 5;, a pointer would simply hold the address where 5 is stored in memory, e.g. int *b = &a;. Before you can use a pointer to cause data to be stored in memory -- the pointer must hold the address for (e.g. it must point to) the beginning of a valid block of memory that you have access to.
You can either provide that valid block of memory by assigning the address of an array to your pointer (where the pointer points to where the array is stored on the stack), or you can allocate a block of memory (using malloc, calloc or realloc) and assign the beginning address for that block to your pointer. (don't forget to free() what you allocate).
The simplest way is to declare a character array and then assign the address to the first element to your pointer (an array is converted to a pointer to the first element on access, so simply assigning the character array to your pointer is fine). For example with the array buf providing the storage and the pointer p holding the address of the first character in buf, you could do:
#include <stdio.h>
#include <string.h> /* for strcspn & strlen */
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (void)
{
char buf[MAXC], /* an array of MAXC chars */
*p = buf; /* a pointer to buf */
if (fgets (p, MAXC, stdin)) { /* read line from stdin */
p[strcspn (p, "\n")] = 0; /* trim \n by overwriting with 0 */
if (strlen (p) > 1) { /* validate at least 2-chars */
printf("%c, %c\n", p[0], p[1]); /* output them */
}
}
return 0;
}
(note: strcspn above simply returns the number of character in your string up to the '\n' character allowing you to simply overwrite the '\n' included by fgets() with '\0' -- which is numerically equivalent to 0)
Example Use/Output
$ ./bin/fgetsmin
Hello
H, e
Look things over and let me know if you have further questions.
#include <stdio.h>
#include <string.h>
int main()
{
char *p;
char str[10],name_first[10];
int i,count;
printf("\nName before reversing the string:::::::::::::");
scanf("%s",&name_first);
// I have taken a name in name_variable and now i want to reverse it
// using pointer for ex
count = strlen(name_first);
p=str+strlen(name_first)-1;
for(i=0;i<count;i++)
{
*(p-i)=*(name_first+i);
}
// now I am getting a reverse of string as a o/p but I want to know
// how p is pointing to the str as I'm not assigning any address,
// is it done automatically by the compiler?
printf("\nname after reversing the string::::::::::::::%s\n",str);
}
Actually you are assigning address to p in the following line of code.
p=str+strlen(name_first)-1;
str is an array so array name keeps the base address. Now adding the length of name_first array and subtracting 1 does the pointer arithmetic hence you are getting the result.
You have created a variable count = strlen(name_first).
So no need to call strlen again to assign the address to p.
For faster way , Just use
p=str+count-1;
The statement:
p=str+strlen(name_first)-1;
assigns to p an address within the memory pointed to by str.
So, let's say str starts at address 0x1000 and has a length of 10 and your name_first has a length of 5. Then p points to 0x1004.
When you loop runs, you are updating the characters in 0x1004, 0x1003, 0x1002, 0x1001 and 0x1000, thereby updating the contents of str.
Hope this clears your doubt.
str is the pointer of the first element of str[10]. In this statement: "p=str+strlen(name_first)-1;" rhs is an address
p, the pointer to a char, is assigned the address of the last char in the char array str in your p= line.
You then proceed to use that pointer to manipulate chars in that block of memory and them print out the manipulate memory content (because str is really just a pointer to the char array anyway).
I have the following code.
#include <string.h>
#include <stdio.h>
int main()
{
char * l;
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
char *second;
strcpy(second, l);
printf("string: %s\n", second);
}
When I run it is says:
The output says "Segmentation fault"....any suggestions??
Thanks
l is an uninitialized pointer; you can't dereference it. You should allocate enough space to write its contents (statically (1) or dynamically (2)).
char l[3]; /* (1) */
#include <stdlib.h>
char *l = malloc(3); /* (2) */
It is the same error with strcpy: second is an unitialized pointer, you can't write into it.
You will learn to despise the Segmentation Fault error...
It's usually called when you try to access memory that is not yours. Most common occurrence would be when you try to access an array index that is out of bounds.
char *l just creates a pointer to a char. What you want is a string, which in C is defined as an array of chars. So when you try to access the next location in memory of whatever l is pointing to (which will probably just be garbage), you're going to access memory that isn't yours, thus Segmentation Fault
You could get memory with malloc or point the pointer to an already existing variable.
char word[3];
char *l;
l = word;
Now you can do such assignments:
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
but now that you want to copy it to another pointer, this pointer must be pointing to another string or you should allocate memory for it.
char *pointer_to_second;
char second[3];
pointer_to_second = second;
or if you prefer to get dynamic memory, change the 3 lines above be this one bellow:
char *pointer_to_second = malloc(sizeof(char) * 3);
after that you can do what you wanted:
strcpy(pointer_to_second, l);
But remember, if you are using a C compiler you must declare all variables at the beggining, otherwise you will get an error. If you are using a C++ compiler you won't have to concern about it.
Segmentation fault happens when you try to access a field that doesn't belong to your vector. For example, if you try this:
printf("The value in position 3 of my pointer is %c\n", *(l + 3));
You will probably get an error, because you pointer have 3 positions and you are trying to acess the 4th one.
I have this custom string copy function and I've noticed that the *dest argument changes upon dereferencing it and modifying its contents:
char *copyArray(char *dest, char *src)
{
char *a = dest;
while (*dest++ = *src++)
;
char *b = dest;
if ( (a-b) != 0)
printf("Dest pointer has changed\n");
return dest;
}
And if you consider the following code:
int main()
{
char name [] = "Hello, there!";
char *new = copyArray(name, "bye");
printf("New is '%s', name is '%s'\n", new, name);
return 0;
}
I get the following output:
Dest pointer has changed
New is 'o, there!', name is 'bye'
Why does this happen?
My intent was for *new to point to the same location name[] points to, but obviously as the address changed, it points to a different place.
I feel that what's happened is that once the copying ended, C moved the original contents of the destination string minus the number of characters changed (4 for "bye") to a new address and assigned that to *dest.
Is this what's really happening? And could somebody please explain to me why?
This is not really work related, I'm just trying to understand better how pointers behave.
Thank you very much for your replies!
The problem occurs here
while (*dest++ = *src++)
;
which in plain english means copy the thing pointed to by src into the thing pointed to by dest, and after that increment both src and dest (that is, advance both pointers to point to the next thing).
Use a copy of the pointer if you want to avoid changing it - eg the a variable you already created, and return that one.
The argument dest is being incremented (in the while condition) four times (as "bye" is 4 characters including the null which will be assigned on the final iteration of the while) inside the function copyArray() and its value is then returned so new points to name + 4.
To have new point to the beginning of name return a from copyArray().
I am new to C and I would like to know the difference between the below two snippet codes.When I try executing first one it works fine,but when I run the second one it gives me segmentation fault.Whats the reason for this behavior?
printf("%c\n",*strptr++);
printf("%c\n",*(strptr+i));
Here is the below code.
#include<stdio.h>
int main(void)
{
char str[100]="My name is Vutukuri";
int i=0;
char *strptr;
strptr=str;
while(*strptr != '\0')
{
printf("%c\n",*strptr++);
//printf("%c\n",*(strptr+i));
//i++;
}
return 0;
}
Entirely different.
The first snippet prints the character at strptr and then increments strptr by one.
The second snippet prints the character at strptr + i.
Apparently, the address strptr refers to an allocated place in memory, while strptr + i points to an unallocated place. If you allocate a string as
char s[LENGTH];
or
char* s = (char*)malloc(LENGTH * sizeof(char));
then you can only use the characters from s[0] to s[LENGTH - 1] (and the string itself can only be LENGTH - 1 long, so there is place for a null terminator). In your case, the pointer strptr + i is probably not in the range s...s + LENGTH - 1.
Maybe you want to replace i with 1.
++ operator first uses the initial value, and then it increments it.
+operator calculates the new value and then uses it.