I think I will understand this concept better if someone can assist me in a current project that I'm working on. I want to use C to edit data at specific memory addresses, using pointers. Specifically, I have two character arrays (strings) which I need to both read data from at specific locations, and also write to at specific locations.
I'm mostly confused about syntax of pointers, such as * and -> and &.
From my understanding, the * refers to the data kept at the current memory address of the pointer. So, for example, if I wanted to edit the data at the beginning memory address of a char *p, I would do something like: (*p) = 'c';
Now, what if I wanted do to alter a character at the 2nd memory address from the beginning of p?
Also, I understand that & refers to the location of the pointer. But I don't know how to use this syntax.
Here is my example:
int orig_length = strlen(original_string); //-1 for \0?
char *poriginal, *pnew_string;
poriginal = &original_string;
while(orig_length>0) {
k = 0;
j = 0;
while(isalpha(*(poriginal+j))) {
j++;
k++;
}
while(k > 0) {
*(pnew_string+(j-k)) = toupper(*(poriginal+k-1)); //toupper
k--;
}
if(*(poriginal+(j)) == '_') {
*(pnew_string+(j)) = ' ';
}
else {
*(pnew_string+(j)) = *(poriginal+(j));
}
orig_length = orig_length - j;
}
*(pnew_string+strlen(pnew_string)) = '\0'; //Syn? Is this actually necessary?
... //program continues...
By the way, this program is meant to take one string "now_i_understand!" and reverse each word, capitalize each word, switch _ to ' ', and leave other punctuation alone: "WON I DNATSREDNU!"
If what you are dealing with is an array of characters (and it is), use array syntax:
pnew_string[j+1] = poriginal[j+1];
Note that this syntax is equivalent to:
*(pnew_string + j + 1) = *(poriginal + j + 1);
but is more readable.
Dealing with most of the other cases you've got should be obvious given this example.
The * and & operators are inverses of each other. A pointer object hold the address of some other object in memory (or it old a null pointer, which doesn't point to any object).
The unary * operator takes a pointer operand, and gives you the object that it points to; this is called dereferencing.
The unary & operator takes an operand that refers to an object of any type, and gives you a pointer to that object. & is the address-of operator.
For example:
int obj = 42; /* obj is an object of type int; it currently holds the value 42 */
int *ptr; /* ptr is a pointer to an int */
ptr = &obj; /* ptr now holds the address of obj */
printf("obj = %d\n", obj); /* prints 42 */
printf("*ptr = %d\n", *ptr); /* also prints 42; *ptr is another name for obj */
The -> operator is shorthand for dereferencing a pointer and accessing a member of what it points to. The prefix must be a pointer to a struct or union. foo->bar means the same thing as (*foo).bar, where foo is a pointer and bar is the name of a member of what foo points to.
You can also perform arithmetic on pointers. If ptr is a pointer pointing to an element of an array, then ptr + 1 points to the next element of the array, ptr + 2 points to the element after that, and so forth.
The [] array indexing operator is actually defined in terms of pointer arithmetic. ptr[2] means exactly the same thing as *(ptr+2). Combine that with the fact that an array name, in most contexts, decays to a pointer to the array's first element, and with a little thought you'll see how arr[2] refers to the third element of the array arr (third because indexing starts at 0).
I strongly recommend sections 4 (Pointers) and 6 (Arrays and Pointers) of the comp.lang.c FAQ; it will likely explain this stuff better than I have.
Related
This question already has answers here:
Why does the arrow (->) operator in C exist?
(3 answers)
Closed 1 year ago.
I am trying to make all the names in the Struct lowercase so that I can compare them and remove them.
int removeNameCard(NameCard *idCard, int *size){
char name[80];
char *ptr;
char rubbish;
int a = 0, c = 0;
printf("removeNameCard():\n");
printf("Enter personName:\n");
scanf("%c", &rubbish); // Why is there a '\n' char here??
fgets(name, 80, stdin);
if((ptr = strchr(name, '\n'))){
*ptr = '\0';
}
if((*size) == 0){
printf("The name card holder is empty\n");
return 0;
}
// Convert everything to Lower Case first
while(name[a]){
name[a] = tolower(name[a]);
a += 1;
}
printf("tolower(): %s", name);
for(int b = 0; b < *size; b += 1){
// Why is this Dot Notation when I passed in a pointer to the Struct?
while (idCard[b].personName)[c]){
(idCard[b].personName)[c] = tolower((idCard[b].personName)[c]);
c += 1;
}
}
for(int i = 0; i < *size; i += 1){
if((idCard[i].personName) == name){
printf("%d. This is from Holder: %s, This is from User: %s", i,(idCard[i].personName),name);
printf("The name card is removed\n");
printf("nameCardID: %d\n", idCard[i].nameCardID);
printf("personName: %s\n", idCard[i].personName);
printf("companyName: %s\n", idCard[i].companyName);
int k = 0;
do{
idCard[i+k].nameCardID = idCard[i+k+1].nameCardID;
strcpy((idCard[i+k].personName),(idCard[i+k+1].personName));
strcpy((idCard[i+k].companyName),(idCard[i+k+1].companyName));
}while((i+k+1) != (*size + 1));
}
}
return 0;
}
However, I am rather confused why the Compiler asked me to use Dot Notation instead of Pointer Notation as I thought I passed in the address of the Struct into *idCard so it should be a pointer if I am not wrong?
And am I wrong for trying to access each individual character in every name of the Struct like this?:
(idCard[b].personName)[c]
Thank you
However, I am rather confused why the Compiler asked me to use Dot Notation instead of Pointer Notation…
idCard[i] is a structure, not a pointer to a structure, so its members are accessed as idCard[i].member, not idCard[i]->member.
idCard[i] is a structure because whenever x is a pointer, x[i] is one of the objects that x points to. It is not the address of the object. You could calculate the address of the object with x+i, and then you could reference the object with *(x+i). And x[i] is actually defined in this way; x[i] is defined to be *(x+i). (In case of expressions generally, E1[E2] is defined to be (*((E1)+(E2))).)
And am I wrong for trying to access each individual character in every name of the Struct like this?: (idCard[b].personName)[c]
This will work, but the parentheses are unnecessary. You can use idCard[b].personName[c]. Due to the C grammar, it is already grouped as (idCard[b].personName)[c].
However, I am rather confused why the Compiler asked me to use Dot Notation instead of Pointer Notation as I thought I passed in the address of the Struct into *idCard so it should be a pointer if I am not wrong?
Arrays are mostly just pointers to the first element in the array (except that the compiler may be aware of the array size).
Because arrays are mostly just pointers; for arrays of integers myInt = myIntArray[x]; is like myInt = *(myIntArray + x); - the pointer dereferencing is implied by array indexing. Note that to access a char in the middle of an int in an array, you could (not portably) use something like myChar = *((char *)(myIntArray + x)) + offset_of_char_in_int);; and this is a little bit like accessing a field inside an array of structures (in that they're both accessing something smaller within an array of larger things).
For arrays of structures; indexing the array causes dereferencing (just like it does for the array of integers); so myIDcardStruct = idCard[i]; is like myIDcardStruct = *(idcard + i);. Because array indexing has implied dereferencing, myIDcardStruct is not a pointer.
The -> operator is like adding the offset of the requested structure's field to the address, casting the address to the requested field's type, and then dereferencing. In other words myInt = myStructPointer->myIntField; is like myInt = (*myStructPointer).myIntField; which is like tempAddress = (void *)myStructPointer + offset_of_myIntField; myInt = *((int *)tempAddress);.
What this means is that if you have an array of structures (which is mostly a pointer to the first structure in the array), indexing the array causes the pointer to be implicitly dereferenced, and using -> also causes implicit dereferencing; and if you do both then you've (implicitly) dereferenced a pointer twice, which is too much dereferencing (because it's not a pointer to a pointer to a structure, or an array of pointers to structures). Because you only want it dereferenced once you have to choose between one implicit deference (array indexing) or the other implicit dereference (->); e.g. you can choose between myInt = idCard[i].nameCardID; or myInt = (idCard + i)->nameCardID;.
Of course the important thing is making code easy to read, and myInt = idCard[i].nameCardID; is easier to read than myInt = (idCard + i)->nameCardID;.
I have currently trouble understanding the following scenario:
I have a multidimensional array of Strings and I want to address it by using pointers only but I always get a Segmentation Fault when using the array annotation on the pointer. This is just an example code I want to use the 3D array in a pthread so I want to pass it in via a structure as a pointer but it just doesn't work and I would like to know why? I thought pointers and arrays are functionally equivalent? Here is the sample code:
#include <stdio.h>
void func(unsigned char ***ptr);
int main() {
// Image of dimension 10 times 10
unsigned char image[10][10][3];
unsigned char ***ptr = image;
memcpy(image[0][0], "\120\200\12", 3);
// This works as expected
printf("Test: %s", image[0][0]);
func(image);
return 0;
}
void func(unsigned char ***ptr) {
// But here I get a Segmentation Fault but why??
printf("Ptr: %s", ptr[0][0]);
}
Thanks in advance for your help :)
I think maybe strdup confuses the issue. Pointers and arrays are not always equivalent. Let me try to demonstrate. I always avoid actual multi-dimension arrays, so I may make a mistake here, but:
int main()
{
char d3Array[10][10][4]; //creates a 400-byte contiguous memory area
char ***d3Pointer; //a pointer to a pointer to a pointer to a char.
int i,j;
d3Pointer = malloc(sizeof(char**) * 10);
for (i = 0; i < 10; ++i)
{
d3Pointer[i] = malloc(sizeof(char*) * 10);
for (j = 0; j < 4; ++j)
{
d3Pointer[i][j] = malloc(sizeof(char) * 4);
}
}
//this
d3Pointer[2][3][1] = 'a';
//is equivalent to this
char **d2Pointer = d3Pointer[2];
char *d1Pointer = d2Pointer[3];
d1Pointer[1] = 'a';
d3Array[2][3][1] = 'a';
//is equivalent to
((char *)d3Array)[(2 * 10 * 4) + (3 * 4) + (1)] = 'a';
}
Generally, I use the layered approach. If I want contiguous memory, I handle the math myself..like so:
char *psuedo3dArray = malloc(sizeof(char) * 10 * 10 * 4);
psuedo3dArray[(2 * 10 * 4) + (3 * 4) + (1)] = 'a';
Better yet, I use a collection library like uthash.
Note that properly encapsulating your data makes the actual code incredibly easy to read:
typedef unsigned char byte_t;
typedef struct
{
byte_t r;
byte_t g;
byte_t b;
}pixel_t;
typedef struct
{
int width;
int height;
pixel_t * pixelArray;
}screen_t;
pixel_t *getxyPixel(screen_t *pScreen, int x, int y)
{
return pScreen->pixelArray + (y*pScreen->width) + x;
}
int main()
{
screen_t myScreen;
myScreen.width = 1024;
myScreen.height = 768;
myScreen.pixelArray = (pixel_t*)malloc(sizeof(pixel_t) * myScreen.height * myScreen.width);
getxyPixel(&myScreen, 150, 120)->r = 255;
}
In C, you should allocate space for your 2D array one row at a time. Your definition of test declares a 10 by 10 array of char pointers, so you don't need to call malloc for it. But to store a string you need to allocate space for the string. Your call to strcpy would crash. Use strdup instead. One way to write your code is as follows.
char ***test = NULL;
char *ptr = NULL;
test = malloc(10 * sizeof(char **));
for (int i = 0; i < 10; i++) {
test[i] = malloc(10 * sizeof(char *));
}
test[0][0] = strdup("abc");
ptr = test[0][0];
printf("%s\n", ptr);
test[4][5] = strdup("efg");
ptr = test[4][5];
printf("%s\n", ptr);
Alternatively, if you want to keep your 10 by 10 definition, you could code it like this:
char *test[10][10];
char *ptr = NULL;
test[0][0] = strdup("abc");
ptr = test[0][0];
printf("%s\n", ptr);
test[4][5] = strdup("efg");
ptr = test[4][5];
printf("%s\n", ptr);
Your problem is, that a char[10][10][3] is something very different from a char***: The first is an array of arrays of arrays, the later is a pointer to a pointer to a pointer. The confusions arises because both can be dereferenced with the same syntax. So, here is a bit of an explanation:
The syntax a[b] is nothing but a shorthand for *(a + b): First you perform pointer arithmetic, then you dereference the resulting pointer.
But, how come you can use a[b] when a is an array instead of a pointer? Well, because...
Arrays decay into pointers to their first element: If you have an array declared like int array[10], saying array + 3 results in array decaying to a pointer of type int*.
But, how does that help to evaluate a[b]? Well, because...
Pointer arithmetic takes the size of the target into account: The expression array + 3 triggers a calculation along the lines of (size_t)array + 3*sizeof(*array). In our case, the pointer that results from the array-pointer-decay points to an int, which has a size, say 4 bytes. So, the pointer is incremented by 3*4 bytes. The result is a pointer that points to the fourths int in the array, the first three elements are skipped by the pointer arithmetic.
Note, that this works for arrays of any element type. Arrays can contain bytes, or integers, or floats, or structs, or other arrays. The pointer arithmetic is the same.
But, how does that help us with multidimensional arrays? Well, because...
Multidimensional arrays are just 1D arrays that happen to contain arrays as elements: When you declare an array with char image[256][512]; you are declaring a 1D array of 256 elements. These 256 elements are all arrays of 512 characters, each. Since the sizeof(char) == 1, the size of an element of the outer array is 512*sizeof(char) = 512, and, since we have 256 such arrays, the total size of image is 256*512. Now, I can declare a 3D array with char animation[24][256][512];...
So, going back to your example that uses
char image[10][10][3]
what happens when you say image[1][2][1] is this: The expression is equivalent to this one:
*(*(*(image + 1) + 2) + 3)
image being of type char[10][10][3] decays into a pointer to its first element, which is of type char(*)[10][3] The size of that element is 10*3*1 = 30 bytes.
image + 1: Pointer arithmetic is performed to add 1 to the resulting pointer, which increments it by 30 bytes.
*(image + 1): The pointer is dereferenced, we are now talking directly about the element, which is of type char[10][3].
This array again decays into a pointer to its first element, which is of type char(*)[3]. The size of the element is 3*1 = 3. This pointer points at the same byte in memory as the pointer that resulted from step 2. The only difference is, that it has a different type!
*(image + 1) + 2: Pointer arithmetic is performed to add 2 to the resulting pointer, which increments it by 2*3 = 6 bytes. Together with the increment in step 2, we now have an offset of 36 bytes, total.
*(*(image + 1) + 2): The pointer is dereferenced, we are now talking directly about the element, which is of type char[3].
This array again decays into a pointer to its first element, which is of type char*. The size of the element is now just a single byte. Again, this pointer has the same value as the pointer resulting from step 5, but a different type.
*(*(image + 1) + 2) + 1: Pointer arithmetic again, adding 1*1 = 1 bytes to the total offset, which increases to 37 bytes.
*(*(*(image + 1) + 2) + 1): The pointer is dereferenced the last time, we are now talking about the char at an offset of 37 bytes into the image.
So, what's the difference to a char***? When you dereference a char***, you do not get any array-pointer-decay. When you try to evaluate the expression pointers[1][2][1] with a variable declared as
char*** pointers;
the expression is again equivalent to:
*(*(*(pointers + 1) + 2) + 3)
pointers is a pointer, so no decay happens. Its type is char***, and it points to a value of type char**, which likely has a size of 8 bytes (assuming a 64 bit system).
pointers + 1: Pointer arithmetic is performed to add 1 to the resulting pointer, which increments it by 1*8 = 8 bytes.
*(pointers + 1): The pointer is dereferenced, we are now talking about the pointer value that is found in memory at an offset of 8 bytes of where pointers points.
Further steps depending on what actually happened to be stored at pointers[1]. These steps do not involve any array-pointer-decay, and thus load pointers from memory instead.
You see, the difference between a char[10][10][3] and a char*** is profound. In the first case, the array-pointer-decay transforms the process into a pure offset computation into a multidimensional array. In the later case, we repeatedly load pointers from memory when accessing elements, all we ever have are 1D arrays of pointers. And it's all down to the types of pointers!
In general, i'm trying to allocate values of first.a and first.b
to a array's in struct secon.
typedef struct {
int a;
int b;
} firs;
//secon is my struct which contains dynamic array
//can i use int here ?
typedef struct {
int *aa;
int *bb;
} secon;
//pointer to secon intialised to NULL;
secon* sp=NULL;
int main()
{
firs first;
//plz assume 2 is coming from user ;
sp=malloc(sizeof(secon)*2);
//setting values
first.a=10;
first.b=11;
/* what i'm trying to do is assign values of first.a and first.b to my
dynamically created array*/
/* plz assume first.a and first.b are changing else where .. that means ,not
all arrays will have same values */
/* in general , i'm trying to allocate values of first.a and first.b
to a array's in struct second. */
for(int i=0; i<2; i++) {
*( &(sp->aa ) + (i*4) ) = &first.a;
*( &(sp->bb ) + (i*4) ) = &first.b;
}
for(int i=0; i<2; i++) {
printf("%d %d \n", *((sp->aa) + (i*4) ),*( (sp->bb) +(i*4) ) );
}
return 0;
}
MY output :
10 11
4196048 0
Problems with my code:
1. whats wrong with my code?
2. can i use int inside struct for dynamic array?
3. what are the alternatives?
4. why am i not getting correct answer?
Grigory Rechistov has done a really good job of untangling the code and you should probably accept his answer, but I want to emphasize one particular point.
In C pointer arithmetic, the offsets are always in units of the size of the type pointed to. Unless the type of the pointer is char* or void* if you find yourself multiplying by the size of the type, you are almost certainly doing it wrong.
If I have
int a[10];
int *p = &(a[5]);
int *q = &(a[7]);
Then a[6] is the same as *(p + 1) not *(p + 1 * sizeof(int)). Likewise a[4] is *(p - 1)
Furthermore, you can subtract pointers when they both point to objects in the same array and the same rule applies; the result is in the units of the size of the type pointed to. q - p is 2, not 2 * sizeof(int). Replace the type int in the example with any other type and the p - q will always be 2. For example:
struct Foo { int n ; char x[37] ; };
struct Foo a[10];
struct Foo *p = &(a[5]);
struct Foo *q = &(a[7]);
q - p is still 2. Incidentally, never be tempted to hard code a type's size anywhere. If you are tempted to malloc a struct like this:
struct Foo *r = malloc(41); // int size is 4 + 37 chars
Don't.
Firstly, sizeof(int) is not guaranteed to be 4. Secondly, even if it is, sizeof(struct Foo) is not guaranteed to be 41. Compilers often add padding to struct types to ensure that the members are properly aligned. In this case it is almost a certainty that the compiler will add 3 bytes (or 7 bytes) of padding to the end of struct Foo to ensure that, in arrays, the address of the n member is aligned to the size of an int. always always always use sizeof.
It looks like your understanding how pointer arithmetic works in C is wrong. There is also a problem with data layout assumptions. Finally, there are portability issues and a bad choice of syntax that complicates understanding.
I assume that wit this expression: *( &(sp->aa ) + (i*4) ) you are trying to access the i-th item in the array by taking address of the 0-th item and then adding a byte offset to it. This is wrong of three reasons:
You assume that after sp[0].aa comes sp[1].aa in memory, but you forget that there is sp[0].bb in between.
You assume that size of int is always 4 bytes, which is not true.
You assume that adding an int to secon* will give you a pointer that is offset by specified number of bytes, while in fact it will be offset in specified number of records of size secon.
The second line of output that you see is random junk from unallocated heap memory because when i == 1 your constructions reference memory that is outside of limits allocated for *secon.
To access an i-th item of array referenced by a pointer, use []:
secon[0].aa is the same as (secon +0)->aa, and secon[1].aa is equal to (secon+1)->aa.
This is a complete mess. If you want to access an array of secons, use []
for(int i=0;i<2;i++)
{
sp[i].aa = &first.a; // Same pointer both times
sp[i].bb = &first.b;
}
You have two copies of pointers to the values in first, they point to the same value
for(int i=0;i<2;i++)
{
sp[i].aa = malloc(sizeof(int)); // new pointer each time
*sp[i].aa = first.a; // assigned with the current value
sp[i].bb = malloc(sizeof(int));
*sp[i].bb = first.b;
}
However the compiler is allowed to assume that first does not change, and it is allowed to re-order these expressions, so you are not assured to have different values in your secons
Either way, when you read back the values in second, you can still use []
for(int i=0;i<2;i++)
{
printf("%d %d \n",*sp[i].aa ),*sp[i].bb );
}
The pointer to my global variable is turning to crud after freeing the local resource that I use to set the value in c.
this is the .c class
char* resource_directory;
void getResourcePath()
{
char *basePath = SDL_GetBasePath();
char* resource_dir = (char*)malloc(37 * sizeof(char));
for(int i = 0; i < 25; i++)
{
resource_dir[i] = basePath[i];
}
strcat(resource_dir, "resources/");
resource_dir[36] = '\0';
*resource_directory = *resource_dir;
free(basePath);
// free(resource_dir); <--- If I free here the value goes to crud
}
(this line below should say the value at resresource_directorydir equals the value at resource_dir) right?
*resource_directory = *resource_dir;
so the value at the address of the first pointer should get the value of the address at the 2nd but after trying to free the resource towards the end of the function.
even doing a print statement of the addresses show that they have different addresses.
SDL_Log("%d, %d", &resource_directory, &resource_dir);
example output : 245387384, 1361037488
I get the feeling that I am making a silly mistake here but I don't know what it is.
This line,
*resource_directory = *resource_dir;
is assigning the first value resource_dir points to, to the uninitialized pointer resource_directory, it's equivalent to
resource_directory[0] = resource_dir[0];
which is clearly not what you want.
You need to assign the pointer
resource_directory = resource_dir;
but you shouldn't use a global variable for that, and specially
Don't malloc() it, you have to free() everything you malloc() and global variables make it hard.
Don't use malloc() for fixed size objects, instead declare it as an array with the appropriate size, like this
char resource_directory[37];
Copy strings with strcpy() instead of writing a loop your self
for(int i = 0; i < 25; i++)
{
resource_dir[i] = basePath[i];
}
woule be
strcpy(resource_dir, basePath);
One thing you should notice when using a global variable like this is that if you call getResourcesPath() more than once, you are going to leak resources, if you must use global variables to carry values that need to live as long as the whole program lives, try to make their initialization static, and you can completely avoid using global variables for that, because everything that you declare and initialized in the stack frame of main() will hafe the same lifetime as the program, so you can pass it as parameters to any function that requires them from within main(), if you have many of these variables, create a struct to hold them, and pass the struct across the functions that need these resources, this is a very common technique in fact.
This statements
SDL_Log("%d, %d", &resource_directory, &resource_dir);
outputs as integer values the addresses of global variables resource_directory and local variable resource_dir. Of course their addresses are different.
As for this statement
*resource_directory = *resource_dir;
then it stores the first character of the string pointed to by resource_dir at the address that is stored in pointer resource_directory. However initially resource_directory was initialized by zero as an object with the static storage duration. So the program has undefined behaviour.
I think you mean the following
resource_directory = resource_dir;
That is you wanted that resource_directory would point to the string built in the function.
And there is no sense to use statement
free(resource_dir); <--- If I free here the value goes to crud
necause in this case statement
resource_directory = resource_dir;
also does not have sense.
If resource_directory need to point to the built in the function string then you shall not destroy it.
Take into account that using magic numbers 37 and 25 makes the program unclear and error-prone.
A pointer is a variable that contains a numeric value which happens to be the address of a memory location. For example, a NULL pointer is a variable containing the value 0. Assigning the notion of "isa pointer" to is a way of notifying the compiler of your intended use: that is, you cannot use pointer syntax on non-pointer variables. But until you do use pointer syntax, they more or less behave like normal variables.
int i = 0;
int* p = &i;
int j;
int* q;
j = i; // j has the same value as i
q = p; // q has the same value as p
At the end of the above code, p and q point to the same address. We only use the * syntax when we want to dereference a pointer:
q = p;
*q = *p; // copies the `int` pointed to by `p` to
// the `int` memory location pointed to by `q`,
// which is the same location.
Note that it is possible to nest pointers:
int** pp = &p;
p is int*, so &p is int**.
pp is a numeric value, it is the address of a memory location that contains an int*. *pp means fetch the value at the memory location contained in pp which will retrieve a second numeric value - the value that is in p, which is itself an int* and thus a second address. **pp will retrieve us the integer to which p points.
Your assignment
*resource_directory = *resource_dir;
copies the pointed-to-values, not the addresses.
Since you have tagged your question as C++ I'm going to conclude by offering this alternative implementation:
std::string resource_dir;
void getResourcePath()
{
char *basePath = SDL_GetBasePath();
resource_dir = base_path;
resource_dir += "resources/";
free(basePath);
}
If you need the c-string value of resource_dir subsequently, use resource_dir.c_str().
Alternatively, if you require a C implementation:
char* resource_dir;
void getResourcePath()
{
const char subPath[] = "resources/";
size_t length;
char *basePath = SDL_GetBasePath();
if (resource_dir)
free(resource_dir);
length = strlen(basePath) + sizeof(subPath);
resource_dir = (char*)malloc(length);
snprintf(resource_dir, length, "%s%s", basePath, subPath);
free(basePath);
}
How do pointers-to-pointers work in C?
When might you use them?
Let's assume an 8 bit computer with 8 bit addresses (and thus only 256 bytes of memory). This is part of that memory (the numbers at the top are the addresses):
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| | 58 | | | 63 | | 55 | | | h | e | l | l | o | \0 | |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
What you can see here, is that at address 63 the string "hello" starts. So in this case, if this is the only occurrence of "hello" in memory then,
const char *c = "hello";
... defines c to be a pointer to the (read-only) string "hello", and thus contains the value 63. c must itself be stored somewhere: in the example above at location 58. Of course we can not only point to characters, but also to other pointers. E.g.:
const char **cp = &c;
Now cp points to c, that is, it contains the address of c (which is 58). We can go even further. Consider:
const char ***cpp = &cp;
Now cpp stores the address of cp. So it has value 55 (based on the example above), and you guessed it: it is itself stored at address 60.
As to why one uses pointers to pointers:
The name of an array usually yields the address of its first element. So if the array contains elements of type t, a reference to the array has type t *. Now consider an array of arrays of type t: naturally a reference to this 2D array will have type (t *)* = t **, and is hence a pointer to a pointer.
Even though an array of strings sounds one-dimensional, it is in fact two-dimensional, since strings are character arrays. Hence: char **.
A function f will need to accept an argument of type t ** if it is to alter a variable of type t *.
Many other reasons that are too numerous to list here.
How do pointers to pointers work in C?
First a pointer is a variable, like any other variable, but that holds the address of a variable.
A pointer to a pointer is a variable, like any other variable, but that holds the address of a variable. That variable just happens to be a pointer.
When would you use them?
You can use them when you need to return a pointer to some memory on the heap, but not using the return value.
Example:
int getValueOf5(int *p)
{
*p = 5;
return 1;//success
}
int get1024HeapMemory(int **p)
{
*p = malloc(1024);
if(*p == 0)
return -1;//error
else
return 0;//success
}
And you call it like this:
int x;
getValueOf5(&x);//I want to fill the int varaible, so I pass it's address in
//At this point x holds 5
int *p;
get1024HeapMemory(&p);//I want to fill the int* variable, so I pass it's address in
//At this point p holds a memory address where 1024 bytes of memory is allocated on the heap
There are other uses too, like the main() argument of every C program has a pointer to a pointer for argv, where each element holds an array of chars that are the command line options. You must be careful though when you use pointers of pointers to point to 2 dimensional arrays, it's better to use a pointer to a 2 dimensional array instead.
Why it's dangerous?
void test()
{
double **a;
int i1 = sizeof(a[0]);//i1 == 4 == sizeof(double*)
double matrix[ROWS][COLUMNS];
int i2 = sizeof(matrix[0]);//i2 == 240 == COLUMNS * sizeof(double)
}
Here is an example of a pointer to a 2 dimensional array done properly:
int (*myPointerTo2DimArray)[ROWS][COLUMNS]
You can't use a pointer to a 2 dimensional array though if you want to support a variable number of elements for the ROWS and COLUMNS. But when you know before hand you would use a 2 dimensional array.
I like this "real world" code example of pointer to pointer usage, in Git 2.0, commit 7b1004b:
Linus once said:
I actually wish more people understood the really core low-level kind of coding. Not big, complex stuff like the lockless name lookup, but simply good use of pointers-to-pointers etc.
For example, I've seen too many people who delete a singly-linked list entry by keeping track of the "prev" entry, and then to delete the entry, doing something like:
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry pointer", and initialize that with the address of the list_head. And then as they traverse the list, they can remove the entry without using any conditionals, by just doing a
*pp = entry->next
Applying that simplification lets us lose 7 lines from this function even while adding 2 lines of comment.
- struct combine_diff_path *p, *pprev, *ptmp;
+ struct combine_diff_path *p, **tail = &curr;
Chris points out in the comments to the 2016 video "Linus Torvalds's Double Pointer Problem".
kumar points out in the comments the blog post "Linus on Understanding Pointers", where Grisha Trubetskoy explains:
Imagine you have a linked list defined as:
typedef struct list_entry {
int val;
struct list_entry *next;
} list_entry;
You need to iterate over it from the beginning to end and remove a specific element whose value equals the value of to_remove.
The more obvious way to do this would be:
list_entry *entry = head; /* assuming head exists and is the first entry of the list */
list_entry *prev = NULL;
while (entry) { /* line 4 */
if (entry->val == to_remove) /* this is the one to remove ; line 5 */
if (prev)
prev->next = entry->next; /* remove the entry ; line 7 */
else
head = entry->next; /* special case - first entry ; line 9 */
/* move on to the next entry */
prev = entry;
entry = entry->next;
}
What we are doing above is:
iterating over the list until entry is NULL, which means we’ve reached the end of the list (line 4).
When we come across an entry we want removed (line 5),
we assign the value of current next pointer to the previous one,
thus eliminating the current element (line 7).
There is a special case above - at the beginning of the iteration there is no previous entry (prev is NULL), and so to remove the first entry in the list you have to modify head itself (line 9).
What Linus was saying is that the above code could be simplified by making the previous element a pointer to a pointer rather than just a pointer.
The code then looks like this:
list_entry **pp = &head; /* pointer to a pointer */
list_entry *entry = head;
while (entry) {
if (entry->val == to_remove)
*pp = entry->next;
else
pp = &entry->next;
entry = entry->next;
}
The above code is very similar to the previous variant, but notice how we no longer need to watch for the special case of the first element of the list, since pp is not NULL at the beginning. Simple and clever.
Also, someone in that thread commented that the reason this is better is because *pp = entry->next is atomic. It is most certainly NOT atomic.
The above expression contains two dereference operators (* and ->) and one assignment, and neither of those three things is atomic.
This is a common misconception, but alas pretty much nothing in C should ever be assumed to be atomic (including the ++ and -- operators)!
When covering pointers on a programming course at university, we were given two hints as to how to begin learning about them. The first was to view Pointer Fun With Binky. The second was to think about the Haddocks' Eyes passage from Lewis Carroll's Through the Looking-Glass
“You are sad,” the Knight said in an anxious tone: “Let me sing you a song to comfort you.”
“Is it very long?” Alice asked, for she had heard a good deal of poetry that day.
“It's long,” said the Knight, “but it's very, very beautiful. Everybody that hears me sing it - either it brings the tears to their eyes, or else -”
“Or else what?” said Alice, for the Knight had made a sudden pause.
“Or else it doesn't, you know. The name of the song is called ‘Haddocks' Eyes.’”
“Oh, that's the name of the song, is it?" Alice said, trying to feel interested.
“No, you don't understand,” the Knight said, looking a little vexed. “That's what the name is called. The name really is ‘The Aged Aged Man.’”
“Then I ought to have said ‘That's what the song is called’?” Alice corrected herself.
“No, you oughtn't: that's quite another thing! The song is called ‘Ways And Means’: but that's only what it's called, you know!”
“Well, what is the song, then?” said Alice, who was by this time completely bewildered.
“I was coming to that,” the Knight said. “The song really is ‘A-sitting On A Gate’: and the tune's my own invention.”
Pointers to Pointers
Since we can have pointers to int, and pointers to char, and pointers to any structures we've defined, and in fact pointers to any type in C, it shouldn't come as too much of a surprise that we can have pointers to other pointers.
Consider the below figure and program to understand this concept better.
As per the figure, ptr1 is a single pointer which is having address of variable num.
ptr1 = #
Similarly ptr2 is a pointer to pointer(double pointer) which is having the address of pointer ptr1.
ptr2 = &ptr1;
A pointer which points to another pointer is known as double pointer. In this example ptr2 is a double pointer.
Values from above diagram :
Address of variable num has : 1000
Address of Pointer ptr1 is: 2000
Address of Pointer ptr2 is: 3000
Example:
#include <stdio.h>
int main ()
{
int num = 10;
int *ptr1;
int **ptr2;
// Take the address of var
ptr1 = #
// Take the address of ptr1 using address of operator &
ptr2 = &ptr1;
// Print the value
printf("Value of num = %d\n", num );
printf("Value available at *ptr1 = %d\n", *ptr1 );
printf("Value available at **ptr2 = %d\n", **ptr2);
}
Output:
Value of num = 10
Value available at *ptr1 = 10
Value available at **ptr2 = 10
A pointer-to-a-pointer is used when a reference to a pointer is required. For example, when you wish to modify the value (address pointed to) of a pointer variable declared in a calling function's scope inside a called function.
If you pass a single pointer in as an argument, you will be modifying local copies of the pointer, not the original pointer in the calling scope. With a pointer to a pointer, you modify the latter.
A pointer to a pointer is also called a handle. One usage for it is often when an object can be moved in memory or removed. One is often responsible to lock and unlock the usage of the object so it will not be moved when accessing it.
It's often used in memory restricted environment, ie the Palm OS.
computer.howstuffworks.com Link>>
www.flippinbits.com Link>>
it's a pointer to the pointer's address value. (that's terrible I know)
basically, it lets you pass a pointer to the value of the address of another pointer, so you can modify where another pointer is pointing from a sub function, like:
void changeptr(int** pp)
{
*pp=&someval;
}
You have a variable that contains an address of something. That's a pointer.
Then you have another variable that contains the address of the first variable. That's a pointer to pointer.
A pointer to pointer is, well, a pointer to pointer.
A meaningfull example of someType** is a bidimensional array: you have one array, filled with pointers to other arrays, so when you write
dpointer[5][6]
you access at the array that contains pointers to other arrays in his 5th position, get the pointer (let fpointer his name) and then access the 6th element of the array referenced to that array (so, fpointer[6]).
How it works:
It is a variable that can store another pointer.
When would you use them :
Many uses one of them is if your function wants to construct an array and return it to the caller.
//returns the array of roll nos {11, 12} through paramater
// return value is total number of students
int fun( int **i )
{
int *j;
*i = (int*)malloc ( 2*sizeof(int) );
**i = 11; // e.g., newly allocated memory 0x2000 store 11
j = *i;
j++;
*j = 12; ; // e.g., newly allocated memory 0x2004 store 12
return 2;
}
int main()
{
int *i;
int n = fun( &i ); // hey I don't know how many students are in your class please send all of their roll numbers.
for ( int j=0; j<n; j++ )
printf( "roll no = %d \n", i[j] );
return 0;
}
A 5-minute video explaining how pointers work:
There so many of the useful explanations, but I didnt found just a short description, so..
Basically pointer is address of the variable.
Short summary code:
int a, *p_a;//declaration of normal variable and int pointer variable
a = 56; //simply assign value
p_a = &a; //save address of "a" to pointer variable
*p_a = 15; //override the value of the variable
//print 0xfoo and 15
//- first is address, 2nd is value stored at this address (that is called dereference)
printf("pointer p_a is having value %d and targeting at variable value %d", p_a, *p_a);
Also useful info can be found in topic What means reference and dereference
And I am not so sure, when can be pointers useful, but in common it is necessary to use them when you are doing some manual/dynamic memory allocation- malloc, calloc, etc.
So I hope it will also helps for clarify the problematic :)