How to print char** - arrays

I have a variable
char **data;
and I'm trying to print the content of the variable. I understand it to be array of arrays. How would I print it?
Thanks

It's a pointer to a pointer not array of arrays
You need use **data to get value
data will give the memory address which data variable holds
*data will give the memory address of the pointer whose address data is holding
**data will give you the actual value
Say you have a variable like
char c = 'X';
char *cp = &c; //cp stores memory address of c
char **cpp = &cp; //now cpp is pointer which points to a existing pointer cp
To get the value stored at the location which pointer points to - we need to dereference the pointer.
printf("%c", *cp); //prints 'X'
printf("%p", *cpp); //prints memory address of cp
printf("%c", **cpp); //prints 'X' (double stars because address->address->value)

Related

Using memory adress from pointer to print character array (string) C

char mening[] = "tjena pa dig hog";
This string contains 16 characters. I am then using a function adresss() to find the memory address of a random character in that array. The function adresss() returns a pointer containing the address. The address is at this moment 0x7ffeefbff5f9.
I now need to know what positions that address is pointing to, example is it pointing to the "t" at position 0 in the array, or maybe it is pointing to "d" at position 9. How do I do this?
Edit:
char* adresss(char mening[]){
//Lots of code going on here
return &mening[i];
}
int main(void){
char mening[] = "tjena pa dig hog";
char* ptr;
ptr = adresss(mening);
printf("%p\n", ptr);
That is basically how I get the memory adress. I want to know what "i" was, inside the main function only knowing the memory adress.
If you have two pointers, both pointing to the same array (or to one beyond the end of the array), then you can subtract them from each other.
For example:
char mening[] = "tjena pa dig hog";
char *pointer_to_mening = &mening[10]; // Pointer to the eleventh character
// Should print 10 (which is the index of the eleventh character)
printf("The distance is %zu\n", pointer_to_mening - mening);

This program is giving output "abc" for both p and c, but how?

When pc is assigning cdefg, why it is printing abc. when it goes to fun it is assigning pc= ""cdefg"
void fun(char *pc)
{
pc = malloc(5);
pc = "cdefg";
}
int main()
{
char *p = "abc";
char *c = p;
fun(p);
printf("%s %s\n",p,c);
}
The reason your program does what it does is that the assignment of pc in fun has nothing to do with assigning p in main. The pointer is passed by value; any changes made by fun get discarded.
If you would like to assign a new value inside a function, do one of three things:
Pass a pointer to pointer, or
Allocate a buffer in the caller, and pass it to the function, along with buffer's length, or
Return the pointer from the function, and assign in the caller.
First approach:
void fun(char **ppc) {
*ppc = "cdefg";
}
...
fun(&p); // in main
Second approach:
void fun(char *pc, size_t len) {
if (len >= 6) {
strcpy(pc, "cdefg");
}
}
...
char p[20]; // in main
fun(p, 20);
Third approach:
char *fun() {
return "sdefg";
}
...
char *p = fun(); // in main
Your program has other issues - for example, malloc-ed memory gets leaked by the assignment that follows.
Try this instead. It actually updates the original pointer, rather than assigning to a copy which is then left dangling:
void fun(char **pc)
{
*pc = malloc(6);
strcpy(*pc, "cdefg");
}
int main()
{
char *p = "abc";
char *c = p;
fun(&p);
printf("%s %s\n",p,c);
}
It also fixed 2 other problems. The buffer of size 5 isn't big enough for the string plus the string terminator character, and you also need to copy the string into the buffer - assignment won't work.
When the function fun is called, the value of the pointer p is copied. Thus, only the local pointer pc in fun is changed. If you want to change the value of a pointer, you should take a double pointer as argument.
By the way, you do not have to call malloc(3) because the string "cdefg" is already present in memory (in rodata). The instruction pc = "cdefg"; puts the address of "cdefg" into pc. You will loose the address of the memory allocated by malloc(3), it's a memory leak.
When you allocated the pointer again in caller function, the value of pointer variable changed. In order to take this new value to the calling function, you have to pass the address of the pointer. ie: pass the pointer by reference.
There are two things at play here, passing by value and reassigning instead of copying.
If we start with the simple reassignment, take a closer look at these two lines:
pc = malloc(5);
pc = "cdefg";
The first lines assign to pc, making pc point to whatever memory malloc returned. The second line reassigns pc to point somewhere else. These two lines are basically the same as having an int variable i and doing
i = 1;
i = 2;
The first assignment you do is lost because the you immediately make another assignment. To make the memory returned by malloc contain the string "cdefg" there are two things you need to do: The first is that you need to allocate six characters, to fit the string terminator, and the second thing you need to do is to copy the string into the memory:
pc = malloc(strlen("cdefg") + 1);
strcpy(pc, "cdefg");
The second issue is more complex, and has to do with how arguments are passed in C. In C the arguments are passed by values which means they are copied and the function only have a local copy of the data in those arguments.
When you pass a pointer, like in your code, then the pointer is copied into the variable pc, and when the function returns the variable goes out of scope and all changes you made to the variable (like reassigning it to point somewhere else) are simply lost.
The solution is to pass arguments by reference. This is unfortunately not possible in C, but it can be emulated using pointers, or rather using pointers to variables. To pass a pointer to a variable that is a pointer, the type is a pointer to a pointer to some other type, so the function should take a pointer to a pointer to char:
void fun(char **ppc) { ... }
The variable ppc points to the variable p from the main function.
Now since ppc is pointing to a variable, you need to use the dereference operator to access the original variable:
*ppc = malloc(strlen("cdefg") + 1);
strcpy(*ppc, "cdefg");
To call the function you use the address-of operator & to create a pointer to the variable:
char *p = "abc";
...
fun(&p);
Because
char *p - in main function
and
char *pc - in fun function
are different variables.

Cant you specify an address of a pointer?

While this question is a bit easy, I really dont know what is the exact explanation about this.
char *ptr = 'a';
I know a char is not a string but isn't that obvious to store 'a' in the first index of the pointer?
The assignment
char *ptr = 'a';
is equivalent to
char *ptr = 97; // This assumes ASCII encoding
While the assignment itself is valid, dereferencing this pointer is not valid.
If you would like to assign a pointer to point to something that has character 'a' in it, you could use a string literal, an array initializer, or take a pointer of a single-character:
char *ptr = "a"; // String literal
char a[] = {'a'}; // Character array
char *ptr = a;
char a = 'a'; // Single character
char *ptr = &a;
You can specify the address of a pointer. Basically it is a pointer to a pointer.
char* ptr = "a";
char** addrOfPtr = &ptr;
Note that storing the 'a' in the first index of the pointer isn't really what is going on here.
The 'a' is located somewhere in the computer's ram. The value stored in ptr is a number you can use to look up the ram location. It is known as an "address" because when people described these locations they made an analogy to home street addresses.
So 'a' is not stored in the first index of the address, any more than you are stored in the first index of your street address. You reside within the home at your street address, and the value for 'a' resides within the memory specified by the address value stored in ptr.
Note that this means the "pointer to a pointer", addrOfPtr, contains the address where the value within ptr resides.
---- Edit to drive the point home ----
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv) {
char* ptr = "a";
char** ptr_ptr = &ptr;
printf("the value of ptr is '%s', and it is located at %p\n", ptr, &ptr);
printf("the value of ptr_ptr is '%p', and it is located at %p\n", ptr_ptr, &ptr_ptr);
return 0;
}
Will print out a pointer's value and address.
the value of ptr is 'a', and it is located at 0x7ffff79642d8
the value of ptr_ptr is '0x7ffff79642d8', and it is located at 0x7ffff79642d0
You can see that the value of ptr_ptr is the address of ptr, showing that a pointer stores the address of a value, in such a way that the syntax is designed to make it easier to get the value at that address than the actual stored address.
A pointer must have an address assigned to it. 'a' is not an address. It is a integer type with a value of 97, assuming ASCII. If you assign ptr the value 97 and try to dereference it you'll most likely get a segmentation fault because the address 97 does not exist.
char *ptr = "a"; is correct because the compiler will store the characters 'a' and \0' in contiguous memory, with the address of 'a' being stored into ptr.

I want know how pointer p is getting assigned to the address of str

#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).

Differences between pointer initializations

I am speaking in Standard, K&R C.
Given:
const char a[] = {1, 2, 3};
const char *p = NULL;
Are these two statements equivalent:
*p = a;
p = a;
Each of them would be on the third line of the snippet.
1 and 2 certainly don't look the same.
What's the difference between the two then?
No.
p = a initializes the pointer to point to something else (usually it copies another pointer or you will point to a reference, ala p = &a.
*p = a initializes what p refers to. You are "dereferencing" (looking at) what p points to. If p points to NULL as in your example, you will crash (this is good! you do not want to accidentally access something and mess your program up).
In this case, p = a will point to the first of the array a[], and *p = a will attempt to change the first of the array (it won't work; you have it declared const).
Here is a small example program in C++, with almost identical syntax to C.
#include <iostream>
int main()
{
char arr[5] { 'a', 'b', 'c' }; // arr[3] and arr[4] are set to 0
char *ptr = arr; //point to 'a'
for (int i = 0; i != 5; i++)
{
*ptr = 'f'; //this changes the array
ptr++; //this changes what the pointer points to; moves it to next in array
}
for (int i = 0; i != 5; i++)
{
std::cout << *ptr << " ";
}
//outputs f f f f f
}
The * operator is what we call the dereference operator. To understand what it does, you must understand exactly what a pointer is.
When you do
char *p;
the "variable" p does not use the same amount of memory as a normal char, it uses more memory: it uses the amount of memory needed to correctly identify a memory position in your computer. So, let's say you use a 32-bit architecture, the variable p occupies 4 bytes (not the 1 byte you would expect from a char).
So, when you do
p = a;
you see clearly that you are changing the contents of the variable p, that is, you are putting another 32-bit number inside it: you are changing the address it is pointing to.
After that line executes, the value of p is the memory address of the character array a.
Now for the dereference operator. When you do
*p = 'Z';
you are telling the compiler that you want to store the value 'Z' ON THE ADDRESS pointed by p. So, the value of p remains the same after this line: it continues to point to the same address. It's the value of this address that has changed, and now contains 'Z'.
So, the final effect of
char a[] = {'a', 'b', 'c'};
char p = a;
*p = 'Z';
is the same as changing the first position of the array a to 'Z', that is:
char a[] = {'a', 'b', 'c'};
a[0] = 'Z';
NOTE: there is a difference when making a pointer point to an array: the variable that contains the array contains only the address of the first element, so a is the same as "the starting address of the array".
Usually you will see the & operator. It is an operator used to obtain the memory address of a variable. For example:
int number = 42;
int pointer = &number;
printf("%d", *pointer);
Here we have them all. The first line creates an integer variable and stores 42 inside it.
The second line creates a pointer to an integer, and stores the address of the variable number inside it.
The third line reades the value on the address pointed by the pointer.
So, the trick is to read *x as on the address pointed by x and &x as the address of x.
The first dereferences a null pointer, and tries to assign it the address of the array. This will be a compiler error, because char != char []. If it weren't, it would likely crash.
The second sets p to point to the the array.
I think you are mistaking:
char a[8];
char *p=a;
which is legal and does the same as:
char a[8];
char *p=NULL;
p=a;
with:
char a[8];
char *p=NULL;
*p=a;
which as others said would generate a compile error or a segmentation fault.
In the left side of declarations you should read *x as pointer(x) while in
statements it must be read as value_pointed_by(x). &x on the other hand
would be pointer_to(x)
Here's a trick I used when I learned C (and still use today).
Whenever you see the * in front of a variable in your code, automatically read it as "what is pointed to by".
So you should be able to easily see that setting "p" to "a" is very different from setting "what is pointed to by p" to "a".
Also, since p is supposed to be pointing at a char, setting that char p is pointing at (currently the "char" at memory location 0 assuming null is 0) to a char pointer (a) is probably going to fail at compile time if you are lucky (depending on your compiler and lint settings it may actually succeed.)
from comment:In a function declaration like f(char c), I usually try to separate out the variable name from the rest of it--so it would be f( (char) c). so c is a char*. Exactly like a variable definition.
Also & usually reads as "The address of", but that gets even more iffy. A few examples of how I read things to myself. May or may not help you.
int a[] = {1,2,3}; // I mentally parse this as (int[]) a, so a is an int array.
int *p; // p is a pointer to "integers"
int i;
p=a; // p acts exactly as a does now.
i=*p; // i is "What is pointed to by" p (1)
i=p; // i is some memory address
i=*a; // i is what is pointed to by a (1)
i=p[1]; // Don't forget that * and [] syntax are generally interchangable.
i=a+1; // Same as above (2).
p=&i; // p is the address of i (it can because it's a pointer)
// remember from hs algebra that = generally reads as "is", still works!
*p=7; // what is pointed to by p (i) is 7;
a=*i; // whoops, can't assign an array. This is the only difference between
// arrays and pointers that you will have to deal with often, so feel
// free to use which ever one you are more comfortable with.
char c='a';
char * d = &c;// d is a char pointer, and it is the address of c
char ** e ; // e is a pointer to a memory location containing
// a pointer to a char!
e=&d; // gets d's address. a pointer to a pointer gets
// the address of a pointer. Messy but gets the job done
**e=5; // what is pointed to by what is pointed to by e is 5.
*e=&'f'; // what is pointed to by e (which is a char * itself, and is still d!)
// is set to the address of the memory location holding the value 'f'.
// does not change c or e, just d!
I haven't touched c in 10 years, so some of this may be a bit wrong, but it helps me to read it out loud that way.
No, they are not equivalent
If p = NULL, then doing *p = a will give you a segmentation fault.
Because "*p" dereferences the pointer wouldnt this make "p" a "char**" ?
This would point "p" to the first array as expected.
I guess they are not the same.

Resources