I'm trying to learn about pointers in the C language. But I have a question regarding dereferencing them.
This piece of code works fine, it displays 'i' as I desire.
Code-1
#include <stdio.h>
void myfunction(char** str);
int main()
{
char *name = "Gianni";
myfuntion(&name);
return 0;
}
void myfunction(char** str){
char* test = *str;
printf("%c", test[1]);
}
But what I guessed to have the same result turns out to be a little bit different. My question is why do I not get the same result from the second piece of code?
I dereferenced the pointer so it points to the first character again and can read it until the '\0' terminator. So I thought it would be possible to display the single characters here as well.
Code-2
#include <stdio.h>
void myfunction(char** str);
int main()
{
char *name = "Gianni";
myfuntion(&name);
return 0;
}
void myfunction(char** str){
printf("%c", *str[1]);
}
This is precedence issue.(Array subscript [] has higher precedence than dereference *). You should try
(*str)[1]
This will give you the correct result. In earlier case (In Code-2) you had undefined behavior. You were de-referencing str[1] which is pointing to out of bound memory.
So initially what you were doing in Code-2
*str[1] --> *(*(str+1))
Now what we did,
(*str)[1] --> *((*str)+1)
Well in the modification you are basically getting the address of the array (string literals are array which decayed into pointer) and then you index into correct position - which will give you the correct result.
Well if you check earlier example you will see the similarity. Earlier code (Code-1) you print temp[1] which is *(temp+1) But what is temp? In the line before you did this temp = *str so what is it you are doing?
*(temp+1) --> *(*str+1) --> *((*str)+1)
Related
I'm trying to get the length of a string using double pointers but for some reason its not displaying correctly. Some explanation would be greatly appreciated. I feel like i'm missing something simple here.
(I am aware this can be done with a single pointer.)
#include <stdio.h>
void find_length(char**);
int main() {
char* p = "this a message";
char** k = &p;
find_length(k);
return 0;
}
void find_length(char **k) {
while (*k != '\0') {
printf("%c", *k);
k++;
}
}
Ask yourself: When you have a pointer to T and you indirect through that pointer what do you get?
You get T
Now, ask yourself: When T is char, the pointer in question is char* i.e. pointer to char; what do you get when you indirect through that?
You get char
Now, ask yourself: When T is char*, the pointer in question is char** i.e. pointer to pointer to char; what do you get when you indirect through that?
You get char*
Now, ask yourself: What is the type of '\0'
It is char.
Does it make sense to compare char* with char? No, it does not. Now, you have a char*, so how could you get a char out of it? By indirecting through it of course.
Another problem is that you are incrementing k. Incrementing a pointer is allowed when it points to element of an array. Does k point to an array of pointers? It does not. There is only one char* being pointed at. If you want to iterate through the array pointed by *k, then you need to increment *k (or a copy of it).
k is pointer to pointer to char
*k is a pointer to char
**k is a char
So when you check for *k != '\0' you check that the pointer to cahr is different from zero, not if the char is different from the null terminator in the string.
When you do the k++ you increase the pointer to pointer to point at the next pointer to char.
Try this instead.
void find_length(char **k) {
char *kk = *k; // temp.
while (*kk != '\0') {
printf("%c", *kk);
kk++;
}
}
My code is compiled fine but the second printf of my code is not printing.
#include<stdio.h>
int main()
{
char * const p="pointerconstant";
printf("%s",p);
*p='B';
printf("\n%s",p);
}
When I run the following program, it outputs..
pointerconstant
pointerconstant
But it should be..
pointerconstant
Bointerconstant
What is the problem here?
i think your issue is similar: https://stackoverflow.com/a/7547849/5809736
From #bdonlan for your code:
Note that if you did this, it would work:
char p[] = "pointerconstant";
printf("first=%s",p);
*p='B';
printf("\nsecond=%s",p);
This is because we're initializing a non-const character array. Although the syntax looks similar, it is treated differently by the compiler.
In this line
*p='B';
You're trying to modify the first byte of the char array that the pointer points to. This doesn't work because that's a read-only part of your program's binary. Fix it by copying it to the stack or heap:
#include<stdio.h>
#include<string.h>
int main()
{
char * const p = strdup("pointerconstant"); // string is copied to the heap
printf("first=%s", p);
*p = 'B';
printf("\nsecond=%s", p);
free(p); // copy of the string on the heap is released again
return 0; // 0 indicates that the program executed without errors
}
The result is:
first=pointerconstant
second=Bointerconstant
On a side note, in my opinion it would be more idiomatic to write *p = 'B'; as p[0] = 'B';, but that's up to you, of course.
Note: this answer is in C, the question is also tagged as C++
Hello I have some trouble with pointer !
#include <stdio.h>
#include <stdlib.h>
void test(char **str)
{
*str = (char *)malloc(sizeof(char) * 2);
*str[0] = 'b';
*str[1] = '\0';
}
int main(void)
{
char *str;
test(&str);
printf("%s\n", str);
return (0);
}
So I pass a pointer of an non allocated string in my function test, then I allocate my string in the function and try to manipulate it but this code segfault so I guess I miss something on my pointer lesson :)
Can you help me to figure out what is happening here ? thank you a lot !
edit : when I remove my return (0) in the main, the code compile and display my char * ! super weird
The array subscript operator [] has higher precedence than the indirection operator *. So the assignment to str is effectively this which is incorrect:
*(str[0]) = 'b';
*(str[1]) = '\0';
You need to add parenthesis:
(*str)[0] = 'b';
(*str)[1] = '\0';
You must write:
(*str)[0]= 'b';
You must first dereference the str and now the indexing will work on the target, the memory allocated by malloc.
Actually, just 'str' itself means he address of character array.
But 'str' means the value of str.
So the str[0] contains the value of 'b' but as you added '' before str[0] (*str[0]), computer trying to find the value where the address is 'b'.
But this address is not allowed for this process. So this program returns segment fault. Thank you.
I am a beginner in C. I wanted to make strcat function using pointers. I made it but don't know what is wrong with it. I used gcc compiler and it gave segmentation fault output.
#include<stdio.h>
#include<string.h>
char scat(char *,char *);
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
while(*q!='\0') printf("the concatenated string is %c",*q);
}
char *scat(char *s,char *t)
{
char *p=s;
while(*p!='\0'){
p++;
}
while(*t!='\0'){
*p=*t;
p++;
t++;
}
return p-s-t;
}
This one works:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *scat(char *,char *); /* 1: your prototype was wrong */
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
printf("cat: %s\n", q); /* 2: you can use %s to print a string */
free(q);
}
char *scat(char *s,char *t)
{
char *p=malloc(strlen(s)+strlen(t)+1); /* 3: you will have to reserve memory to hold the copy. */
int ptr =0, temp = 0; /* 4 initialise some helpers */
while(s[temp]!='\0'){ /* 5. use the temp to "walk" over string 1 */
p[ptr++] = s[temp++];
}
temp=0;
while(t[temp]!='\0'){ /* and string two */
p[ptr++]=t[temp++];
}
return p;
}
You have to allocate new space to copy at the end of s. Otherwise, your while loo[ will go in memory you don't have access to.
You shoul learn about malloc() here.
It is undefined behaviour to modify a string literal and s, and eventually p, is pointing to a string literal:
char* s = "james";
s is passed as first argument to scat() to which the local char* p is assigned and then:
*p=*t;
which on first invocation is attempting to overwite the null character an the end of the string literal "james".
A possible solution would be to use malloc() to allocate a buffer large enough to contain the concatentation of the two input strings:
char* result = malloc(strlen(s) + strlen(p) + 1); /* + 1 for null terminator. */
and copy them into it. The caller must remember to free() the returned char*.
You may find the list of frequently asked pointer questions useful.
Because p goes till the end of the string and then it starts advancing to illegal memory.
That is why you get segmentation fault.
It's because s points to "james\0", string literal & you cannot modify constant.
Change char *s="james"; to char s[50]="james";.
You need to understand the basics of pointers.
a char * is not a string or array of characters, it's the address of the beginning of the data.
you can't do a char * - char* !!
This is a good tutorial to start with
you will have to use malloc
You get a segmentation fault because you move the pointer to the end of s and then just start writing the data of p to the memory directly following s. What makes you believe there is writable memory available after s? Any attempt to write data to non-writable memory results in a segmentation fault and it looks like the memory following s is not writable (which is to expect, since "string constants" are usually stored in read-only memory).
Several things look out of order.
First keep in mind that when you want to return a pointer to something created within a function it needs to have been malloc'ed somewhere. Much easier if you pass the destination as an argument to the function. If you follow the former approach, don't forget to free() it when you're done with it.
Also, the function scat has to return a pointer in the declaration i.e. char *scat, not char scat.
Finally you don't need that loop to print the string, printf("%s", string); will take care of printing the string for you (provided it's terminated).
At first, your code will be in infinte loop because of the below line. you were supposed to use curely braces by including "p++; t++ " statements.
while(*t!='\0')
*p=*t;
though you do like this, you are trying to alter the content of the string literal. which will result in undefined behavior like segmentation fault.
A sequence of characters enclosed with in double quotes are called as string literal. it is also called as "string". String is fixed in size. once you created, you can't extend its size and alter the contents. Doing so will lead to undefined behavior.
To solve this problem , you need to allocate a new character array whose size is sum of the length of two strings passed. then append the two strings into the new array. finally return the address of the new array.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* scat(char *,char *);
void append(char *t , char *s);
int main(void)
{
char *s="james";
char *t="bond";
char *n = scat(s,t);
printf("the concatenated string is %s",n);
return 0;
}
char* scat(char *s,char *t)
{
int len = strlen(s) + strlen(t);
char *tmp = (char *)malloc(sizeof(char)* len);
append(tmp,s);
append(tmp,t);
return tmp;
}
void append(char *t , char *s)
{
//move pointer t to end of the string it points.
while(*t != '\0'){
t++;
}
while( *s != '\0' ){
*t = *s;
t++;
s++;
}
}
I am trying to understand how pointer incrementing and dereferencing go together, and I did this to try it out:
#include <stdio.h>
int main(int argc, char *argv[])
{
char *words[] = {"word1","word2"};
printf("%p\n",words);
printf("%s\n",*words++);
printf("%p\n",words);
return 0;
}
I expected this code to do one of these:
First dereference then increase the pointer (printing word1)
First dereference then increase the value (printing ord1)
Dereference pointer + 1 (printing word2)
But compiler won't even compile this, and gives this error: lvalue required as increment operand am I doing something wrong here?
You cannot increment an array, but you can increment a pointer. If you convert the array you declare to a pointer, you will get it to work:
#include <stdio.h>
int main(int argc, char *argv[])
{
const char *ww[] = {"word1","word2"};
const char **words = ww;
printf("%p\n",words);
printf("%s\n",*words++);
printf("%p\n",words);
return 0;
}
You need to put braces around the pointer dereference in the second printf, e.g.:printf("%s\n",(*words)++); Also, if you're attempting to get number 2 in your list there, you need to use the prefix increment rather than postfix.
words is the name of the array, so ++ makes no sense on it. You can take a pointer to the array elements, though:
for (char ** p = words; p != words + 2; ++p)
{
printf("Address: %p, value: '%s'\n", (void*)(p), *p);
}
Instead of 2 you can of course use the more generic sizeof(words)/sizeof(*words).
The problem is with this line:
printf("%s\n",*words++);
It is read as *(words++), i.e. increment a block of memory. That doesn't make sense, it is a bit like trying to do:
int a = 1;
(&a)++; // move a so that it points to the next address
which is illegal in C.
The problem is caused by the distinction between arrays and pointers in C: (basically) an array is a block of memory (allocated at compile time), while a pointer is a pointer to a block of memory (not necessarily allocated at compile time). It is a common trip-up when using C, and there are other question on SO about it (e.g. C: differences between char pointer and array).
(The fix is described in other answers, but basically you want to use a pointer to strings rather than an array of strings.)