pointer to address using another pointer C - c

I've got a function which receives a pointer to a string.
Now I want to duplicate this pointer, so I could run on the string with one pointer, and have another pointer which saves the beginning of the string. I hope my question is clear, I don't want to create a pointer to the pointer (which points to where the first pointer points and changes with it), I want a pointer which will point to the address of which the first pointer points.
I tried many different ways but none of them worked, this is my latest try, I keep getting
"initialization makes pointer from integer without a cast"
int move_chars (char *str, int start, int end, int dist){
int strsize = end - start + 1;
char *p = *str;

Since p is of type char * and str is also of type char *, you just need to do:
char *p = str;
To make p point to the same memory location as str.
Your code:
char *p = *str;
Attempts to copy into p the value of the first char at the memory location that str points to, and since p is expecting another memory location and not a char, you get an error.
Your error says that "initialization makes pointer from integer without a cast". This is telling you what's happening: The compiler thinks you are manually pointing p to a specific memory location, using the value of the char *str returns as an integer. This is technically doable, but you are required to manually cast the integer into a pointer, just so it's clear you're doing what you intended, and it's not a bug like in your case.

Use
char *p = str;
to declare a pointer to a char and initialise it with the value of another char pointer.

char *p = str
This will declare a pointer to character and makes p point to the memory location where str points

Related

How does malloc know which type the returned pointer is pointing at?

I'm learning pointers and memory allocation with C. I've used the snippet below to manually allocate some bunch of bytes to copy:
char *s = get_string("s: "); // this is included in cs50 library and it returns a char pointer
char *t = malloc(strlen(s) + 1); // +1 for "\0"
...
free(t);
My question is this, why do we declare t as it points to a char value? How does malloc know that the pointer t points at a char value, even if we did not enter any "clue" about using char?
It doesn't, and it doesn't need to. malloc allocates a block of exactly as many bytes as you tell it to, and returns a void* pointer to it. The pointer is then implicitly converted to char* when the assignment is made. See this for more insight.

Pointer to character array output

When we declare a pointer to any integer say we declare it like
int i=5;
int *p=&i;
We use *p to get the value 5 and if we want the address we use p without asterisk sign to get the address. But in case of character array, when we say
char *str="HELLO";
We simply use str to get "HELLO" as output in printf function. Like this,
printf("%s",str);
Here we used str without asterisk.
Why aren't we getting an address and instead getting "HELLO" as output here while we get address in case of pointers to integers when we use the pointer variable without asterisk?
Okay first of all int *p=5; is wrong! you cant do that in the declaration of a pointer. at That time the pointer expects an adress. You should do int *p; and then *p = 5; to assign the value to it.
printf("%s",str); // prints the value of the variable, because its a pointer.
printf("%s",*str); // the * will cause to a segmentation fault
int *p // the * there is just used to tell the compiler that you are declaring a pointer of type integer.
/* another scope after declaring your pointer */
*p //is used to get value of a pointer variable.(dereference it)
&p //is used to get the adress of a pointer variable.
p //contains an adress.

Two ways of viewing a char ** pointer chain and can pointer types be mixed?

Suppose I have the variable declaration char **p. Does that mean that p is a pointer to a char pointer or that p is a pointer to a pointer of some type that points to a char?
There is a subtle difference between these two chains of pointers.
In other words, what I am trying to ask is given a char pointer to a pointer char **p, *p can obviously be a pointer to a char *, but could it also point to some other pointer type like void * which in turn points to a char?
The type of *p is always char *. It cannot be a void* that happens to be pointing to a char.
Pointer types are derived from some other type - an object type, a function type, or an incomplete type. The type from which the pointer is derived is called its reference type (C99, 6.2.5.20).
The reference type of char** is char*, meaning that dereferencing char** expression yields a char*.
A pointer contains an address. The C compiler uses the variable type such as char of a definition such as char *pC; to know how to access the data at the address contained in the pointer variable pC. So to C all addresses are pretty much the same, at least for all the main stream computer architectures, and the type just tells the C compiler how many bytes of memory to access when dereferencing the pointer or dereferencing the pointer pointed to by a variable.
So a definition such as char **p; tells the compiler that the variable p contains the address of a memory location, which is accessed by reading the number of bytes of a pointer, that points to another address, which is accessed by reading the number of bytes of a pointer, and that the address pointed to contains the address of a char.
And remember that with the C programming language you can use a cast to persuade the compiler to accept almost anything.
And a void * pointer variable is by definition capable of holding a pointer to any data type.
However it is your responsibility that what you are doing actually makes sense. So it is assumed the void * pointer contains the address of a character; that when the variable char **p; is dereferenced as in char aChar = **p; it is up to the programmer that the variable p contains a valid address and that the memory location whose address is pointed to, *p, contains a valid address. Or if you are doing something like char aStr[128]; strcpy (aStr, *p); then the pointer address pointed to by *p contains the address of a zero terminated string of characters.
And to some extent it depends on the C compiler. Some are more accepting than others. Some will issue warnings and some may issue errors and it probably also depends heavily on the compiler options selected for the compile.
Doing a test compile with Visual Studio 2017 Community Edition I can do the following:
char aStr[] = "this is a string";
void *p = aStr; // perfectly fine
char *pc = aStr; // perfectly fine
char **pp = &p; // warning C4133: 'initializing': incompatible types - from 'void **' to 'char **'
char **pp2 = (char **)&p; // perfectly fine since we are casting the pointer
char **pp3 = &aStr; // warning C4047: 'initializing': 'char **' differs in levels of indirection from 'char (*)[17]'
By the way, the last definition, char **pp3 = &aStr; really should be an error since if you dereference pp3 you do not get a valid pointer to a string.
However using the debugger to look at pp, it points to a valid pointer to a string and I can see the text of aStr.
In C programming language char **p will be described as, p is a pointer of pointer to a char. That means p can hold a address of another char pointer.
For example:-
char c = 'A';
char *b = &c;// here b is a char pointer so it can hold the address of a char variable which is c
char **p = &b;// p is a pointer of pointer to a char so here it can hold the address of a pointer of char i.e. b.
printf("%c", **p);// correct and will print A
Now here p is not a void pointer but you can make p also a void * pointer. So following is also correct
void **p = &b;
But to get the value of char c we have to type cast it like below
printf("%c", **p);// Not correct and will not print A
printf("%c", **((char **)p));//correct, first we type cast it to a pointer of pointer to char and dereference it to get the value stored in c
If you use the right-left rule on the declaration you’d see that:
you start with identifier p (P)
p has nothing on the right
you go left to the first * pointer (*P)
you go left again and you see * pointer (**P)
then you go left again and see char (char **P)
all together you can make the conclusion:
P is a pointer to a pointer to char.
Which is a fancy way of saying P is a double pointer to char.

can a character be pointed by a pointer in c

Though we can use a pointer to point an array of characters i.e. strings but can a single character be pointed by a pointer in C?
E.g. Is this code valid?
char *p='a';
Yes, of course you can use a pointer to point to a single character, but you can't go about it in the way that you propose.
char* p = 'a';
is just as incorrect as
int* q = 5;
You're assigning a character value to a pointer. Remember that a pointer is a memory address, so char* p = 'a'; means that you think that there's a char in the memory address 'a'. That's probably not what you want, and conceptually it makes no sense.
You can accomplish what you want like this:
char c = 'a';
char* p = &c;
char *p=&a; is valid, where a is a single character. It's a char * that points to a constant of a single character.
[Corrected per #RedAlert's comment]

Why is a pointer to a pointer incompatible with a pointer to an array?

OK, I'm having trouble understanding pointers to pointers vs pointers to arrays.
Consider the following code:
char s[] = "Hello, World";
char (*p1)[] = &s;
char **p2 = &s;
printf("%c\n", **p1); /* Works */
printf("%c\n", **p2); /* Segmentation fault */
Why does the first printf work, while the second one doesn't?
From what I understand, 's' is a pointer to the first element of the array (that is, 'H').
So declaring p2 as char** means that it is a pointer to a pointer to a char. Making it point to 's' should be legal, since 's' is a pointer to a char. And thus dereferencing it (i.e. **p2) should give 'H'. But it doesn't!
Your misunderstand lies in what s is. It is not a pointer: it is an array.
Now in most contexts, s evaluates to a pointer to the first element of the array: equivalent to &s[0], a pointer to that 'H'. The important thing here though is that that pointer value you get when evaluating s is a temporary, ephemeral value - just like &s[0].
Because that pointer isn't a permanent object (it's not actually what's stored in s), you can't make a pointer-to-pointer point at it. To use a pointer-to-pointer, you must have a real pointer object to point to - for example, the following is OK:
char *p = s;
char **p2 = &p;
If you evaluate *p2, you're telling the compiler to load the thing that p2 points to and treat it as a pointer-to-char. That's fine when p2 does actually point at a pointer-to-char; but when you do char **p2 = &s;, the thing that p2 points to isn't a pointer at all - it's an array (in this case, it's a block of 13 chars).
From what I understand, 's' is a pointer to the first element of the array
No, s is an array. It can be reduced to a pointer to an array, but until such time, it is an array. A pointer to an array becomes a pointer to the first element of the array. (yeah, it's kinda confusing.)
char (*p1)[] = &s;
This is allowed, it's a pointer to an array, assigned the address of an array. It points to the first element of s.
char **p2 = &s;
That makes a pointer to a pointer and assigns it the address of the array. You assign it a pointer to the first element of s (a char), when it thinks it's a pointer to a pointer to one or more chars. Dereferencing this is undefined behavior. (segfault in your case)
The proof that they are different lies in sizeof(char[1000]) (returns size of 1000 chars, not the size of a pointer), and functions like this:
template<int length>
void function(char (&arr)[length]) {}
which will compile when given an array, but not a pointer.
Here's the sample that works, plus printouts of pointer addresses to make things simple to see:
#include <stdio.h>
char s[] = "Hello, World";
char (*p1)[] = &s;
char *p2 = (char*)&s;
int main(void)
{
printf("%x %x %x\n", s, p2, *p2);
printf("%x\n", &s); // Note that `s` and `&s` give the same value
printf("%x\n", &s[0]);
printf("%c\n", **p1);
printf("%c\n", *p2);
}

Resources