Reputation: 43
So I have the following code, I am trying to understand the basics of pointers, so I want to change the value/string inside first
, while also preserving it hence using second
.
Problem is, whatever the input is, the function will print 0
followed by 1
(the value of i
)
then crash. I can clearly see it has to do the with loop, but I can't understand why!
Can anyone explain to me why this is happening and how I can avoid this?
#include <stdio.h>
#include <string.h>
void spells( char **str ){
int i = 0, len = strlen(*str);
while( i < len ){
printf("%d\n",i); //just to check
if( ( (int)*str[i] )%3 == 0 ){// if the ascii value is divided by 3
*str[i] = '#';
}
i++;
} puts("done");
}
int main(){
char first[20];
char* second = &first;
scanf("%s", first);
spells( &second );
printf("%s", second);
printf("\n%s", first);
return 0;
}
Upvotes: 0
Views: 104
Reputation: 30936
Don't complicate things - here you are complicating things (By the way you accessed array index out of bound and then you got seg fault in the called function).
Easy way to do things
char* second = first;
Array decays into pointer to the first element. Then with the same logic you do one thing
spells( second );
And then
void spells( char *str ){
size_t i = 0, len = strlen(str);
while( i < len ){
printf("%zu\n",i); //just to check
if( str[i] % 3 == 0 ){// if the ascii value is divided by 3
str[i] = '#';
}
i++;
}
puts("done");
}
You are not creating any copy - well if you need to use allocate memory or just copy it to some already allocated memory.
For your clarity &first
is of type char (*)[20]
. pointers are not same if the values are equal. You are assigning the value of it to char*
and the you pass it's address. Now when you pass it to the function you do this *(*(str+i))
So now str
is being incremented by i*sizeof char**
- what ever the size of char**
maybe it will result in the accessing the memory out of bound, resulting in undefined behavior which in your case turns out to be segmentation fault.
scanf
use can be way better by doing two thing
if( scanf("%19s", first) != 1){
fprintf(stderrm,"%s\n","Error in input");
exit(1);
}
saving you from possible case of buffer overrun and also checking whether the input got successful or not.
To be clear, my earlier edit was lacking in explaining the problem. To be more explicit, the pointers have two aspect to it - it's value and it's type. The second dictates all the pointer arithmetic.
Here when I said incrementing str
would be out of bound by 80
Bytes that will be true only if relevant type information is passed to the function. Something like
spells(&first)
and
void spell(char(*str)[20])
But here we didn't pass that information - we instead assigned the value of char(*)[20]
to a char*
.(Ofcourse compiler complained) And started working with char**
.
Now when I say
str+i
Actually we move
str+ i*sizeof(str)
more clearly
str+ i*sizeof(char**)
Here in your case this str
originally contains some arbitrary address of a char*
, it has no relation with address directly. This memory location now it points to after addition is not your concern and that is some memory to which you have no permission to access.
With (*str)
now you get the address of the base of the array. Then you index into it. That's a right thing to do and doesn't create any illegal memory access.
Upvotes: 1
Reputation: 28685
Try doing this:
(it is a precedence problem. Hint: if you did str[1]
inside that function what had to be its value?)
if( (*str)[i] %3 == 0 ){// if the ascii value is divided by 3
(*str)[i] = '#';
}
But you are not preserving anything this way because from spells
function you are still modyfing the instance of the string created inside main: char first[20]
.
If you want to preserve anything make a copy of the string and operate on the copy.
Upvotes: 2