I'm quite new in C language, so this "problem" is very confusing for me.
I wanted to create 2D array using array of int pointers (rows) which points to arrays of ints (columns) in one block of memory. I did it and it works but I'm not sure why after I checked something.
I've used malloc to allocate 48 bytes (2x4 array) in the heap (I'm on x86-64 machine):
int **a;
a = (int **)malloc(sizeof(int*) * 2 + sizeof(int) * 2 * 4);
Now lets assume that this is the whole 48 bytes in memory. I wanted 2 row's array so I needed 2 pointers to arrays of ints - a[0], a[1]:
----------------------------------------------------------------
| a[0] | a[1] | |
----------------------------------------------------------------
^
|
I assumed that all pointers are 8 bytes long and that address of a[2] (arrow) is the place where I can start storing my values (arrays of ints). So I did...
int *addr = (int*)&a[2];
a[0] = addr;
addr += 4;
a[1] = addr;
This is working perfectly fine, I can easily fill and print 2D array. Problem is that when I was writing int *addr = (int*)&a[2]; I was sure that this will be the address of a[0] plus 2 * 8 bytes, but it wasn't. I've checked it at another example with this simple code:
int *p;
int **k;
p = (int*) malloc(30);
k = (int**) malloc(30);
printf("&p = %p %p %p\n", &p[0], &p[1], &p[2]);
printf("&k = %p %p %p\n", &k[0], &k[1], &k[2]);
Output:
&p = 0x14d8010 0x14d8014 0x14d8018 <-- ok (int = 4 bytes)
&k = 0x14d8040 0x14d8048 0x14d8050 <-- something wrong in my opinion (ptrs = 8 bytes)
My question is: Why the third address of the pointer in array is 0x14d8050 not 0x14d8056. I think it might be because 0x14d8056 is not the best address for ints but why is that and why it happens only when dealing with array of pointers?? I've checked this on x86 machine and pointer has "normal" values
&p = 0x8322008 0x832200c 0x8322010
&k = 0x8322030 0x8322034 0x8322038
I know this might be an obvious or even stupid question for someone so please at least share some links with information about this behavior. Thank you.
Numbers prefixed by 0x are represented in hexa decimal.
Thus, 0x14d8048 + 8 == 0x14d8050 is expected.
as timrau said in his comment 0x14d8048 + 8 is not 0x14d8056 but 0x14d8050 because it's hexadecimal
concerning your 2D array , I'm not sure why it worked but that's not the way to create one.
there are two ways for creating a 2D array , the first and simple one is " statically " and it goes like this : int a[2][4]; .
the second one , the one you tried , is dynamically , the slightly more complicated and it goes like this
int **a;
int i;
a = malloc(2 * sizeof(*int));
for(i = 0 ; i < 2 ; i++)
a[i] = malloc(4 * sizeof(int));
Related
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!
I am a mid-level programmer, working to learn Standard C. I’m currently struggling through a class exercise which involves using pointers to store different kinds of data types into an array of type char.
Suppose I have a large char array:
static char arr[1000];
As my professor explained it, I can consider this a chunk of local memory, where each element in the array has a granularity of one byte. That seems useful. Now suppose I want to take the first four bytes/elements and store an int:
int a = 100;
int* ptr = (int*)arr;
*ptr = a;
As I understand it, the second line creates an int* pointer, and then points it at the beginning of array arr. The third line writes the value of a into that location. Because ptr is a pointer of type int and because arr has plenty of space, this write four bytes / four element’s worth of data because sizeof(int) == 4. Watching this carefully through my debugger seems to confirm this.
So far, so good. Now let's say I wanted to expand this concept. Let’s say I wanted to store the following into my array, in this order:
int a = 100;
int b = 200;
char* str = “My dog has fleas”
int c = 300;
Which would logically look like this:
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
--------------------------------------------------------------------------------------
[ 100 ] [ 200 ] M y d o g h a s f l e a s \0 [ 300 ]
I need to be able to store data into the array in this manner, and then later, knowing the array structure in advance, be able to read the array. Below is my code & output, sorry in advance for the long length. It compiles but does not work. Scrutinizing it with my debugger has been very confusing; I can't tell where (and how often) I'm going off-track. If anyone has any insight or advice, I will be very grateful.
int main(){
static char arr[1000];
int a = 100;
int b = 200;
char* str = "My dog has fleas";
int c = 300;
// Create pointers to load data:
int* ptrA = arr; // points to start of array
int* ptrB = ptrA + sizeof(int); // points 4 bytes into array
char* ptrStr = ptrB + sizeof(int); // points 8 bytes into array
int* ptrC = ptrStr + sizeof("My dog has fleas"); // points to after the string
// (I don't know how to use sizeof() to measure the actual length of the string
// Load data into my array
*ptrA = a; // Assign int 100 into the array?
*ptrB = b; // Assign int 200 into the array?
*ptrStr = memcpy(ptrStr, str, sizeof("My dog has fleas")); // Write "My dog has fleas" into the array?
*ptrC = c; // Assign int 300 into the array?
// Knowing the array's structure, walk it and print results:
char* walkIt = arr;
int counter = 0;
while (counter < 30) {
if (counter == 0) {
// we are pointing at what should be the first int
int* tmpPtr1 = (int*)walkIt;
printf("%d ", *tmpPtr1);
}
else if (counter == 4) {
// we are pointing at what should be the second int
int* tmpPtr2 = (int*)walkIt;
printf("%d ", *tmpPtr2);
}
else if (counter == 8) {
// we are pointing at what should be the string
printf("%s ", walkIt);
}
else if (counter == 25) {
// we are pointing at what should be the third int
int* tmpPtr3 = (int*)walkIt;
printf("%d ", *tmpPtr3);
}
walkIt++; // Continue walking the array
counter++; // Don't walk too far
}
return 0;
}
Output is this:
100 0 0
First of all your professor is wrong, while it's true that under the hood things maybe be in that way, dereferencing pointers obtained by casting a pointer to a different type violates strict aliasing rule, which is an assumption made by the compiler that two pointers of different types can't refer to the same memory thus allowing optimizations on such pointers.
Going back to your code, the problem is how you are calculating the offset from the base address, eg:
int* ptrB = ptrA + sizeof(int);
Now, ptrA is of int*, and adding an integer offset to a pointer implicitly multiplies the offset by the size of the element pointed. Which means that you aren't adding sizeof(int) bytes but sizeof(int)*sizeof(int) bytes.
To force adding a specific amount of bytes you must cast the pointer to a char* so that adding sizeof(int) bytes just adds sizeof(int)*sizeof(char) == sizeof(int)*1 bytes.
int* ptrB = (char*)ptrA + sizeof(int); // points 4 bytes into array
Mind that this code is unsafe and it's bound to fail, using an union would be a better solution.
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
See the following example
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt;
Serial.println(sizeof(testInt) / sizeof(int)); // returns 3
Serial.println(sizeof(point) / sizeof(int)); // returns 1
(This is a snipplet from Arduino Code - I'm sorry, I don't "speak" real C).
The easy answer is no, you cannot. You'll probably want to keep a variable in memory which stores the amount of items in the array.
And there's a not-so-easy answer. There's a way to determine the length of an array, but for that you would have to mark the end of the array with another element, such as -1. Then just loop through it and find this element. The position of this element is the length. However, this won't work with your current code.
Pick one of the above.
Also doing an Arduino project here...
Everybody on the internet seems to insist it's impossible to do this...
and yet the oldest trick in the book seems to work just fine with null terminated arrays...
example for char pointer:
int getSize(char* ch){
int tmp=0;
while (*ch) {
*ch++;
tmp++;
}return tmp;}
magic...
You can infer the length of an array if you have an array variable.
You cannot infer the length of an array if you have just a pointer to it.
You cannot and you should not attempt deduce array length using pointer arithmetic
if in C++ use vector class
You can if you point the the whole array and NOT point to the first element like:
int testInt[3];
int (*point)[3];
point = testInt;
printf( "number elements: %lu", (unsigned long)(sizeof*point/sizeof**point) );
printf( "whole array size: %lu", (unsigned long)(sizeof*point) );
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
Technically yes, there is a way when code has a true pointer to an array as the array size is in the type as with int (*array_pointer)[3].
This differs from OP's code as the pointer point is not a pointer to an array, but a pointer to an int.
The line point = testInt; converts the array testInt to the address of the first element of the array (which is an int *) and assigns that to point. Thus the array size info is lost.
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt; // Get the address of testInt[0]
int (*array_pointer)[3] = &testInt; // Get the address of the array
printf("%zu\n", sizeof(testInt) / sizeof(int));
printf("%zu\n", sizeof(point) / sizeof(int));
printf("%zu\n", sizeof(*point) / sizeof(int));
printf("%zu\n", sizeof(*array_pointer) / sizeof(int));
printf("%p\n", (void *) testInt);
printf("%p\n", (void *) point);
printf("%p\n", (void *) array_pointer);
Sample output
3
2
1
3
0xffffcbc4
0xffffcbc4
0xffffcbc4
Pointers point and array_pointer both have values that point to the same location in memory, but the pointers differ in type.
With C99 or later that support variable length arrays, code could have been the below and achieved similar results without explicitly coding a 3 in the pointer definition.
int (*array_pointer_vla)[sizeof testInt/sizeof testInt[0]] = &testInt;
printf("%zu\n", sizeof(*array_pointer_vla) / sizeof(int));
Output
3
I see now see similarities to #user411313 answer. Perhaps the deeper explanation and VLA discussion will be useful.
Probably I just lack understanding of how malloc works, but I don't see an error with my code:
int amount_integers = 2;
int *pointer_to_allocated_memory = (int*)malloc(amount_integers * sizeof(int));
for (int i = 0; i < amount_integers; i++)
{
int *address = &(pointer_to_allocated_memory)[i * sizeof(int)];
*(address) = 0;
}
I'd like to initialize memory for an arbitrary amount of integers (amount_integers could be something else than 2). However, the malloc in line 2 seems to misfunction. MSVC's debugger will break at this point (without having defined a breakpoint). When continuing, it will encounter an access writing violation at line 6 (*(address) = 0;) when i is 1.
What I think I'm accessing:
v pointer_to_allocated_memory[0 * sizeof(int)]
... | sizeof(int) | sizeof(int) |
^ pointer_to_allocated_memory[1 * sizeof(int)]
These should be allocated. Why does the application crash?
The array index is not indexing bytes but array elements, in your case ints:
int *address = &(pointer_to_allocated_memory)[i];
valid values for i are 0 and 1
Because you misunderstand how pointer arithmetic works. It doesn't work with bytes, it works with chunks of memory of sizeof(T) bytes, T being the pointer's pointed type. So
int *address = &(pointer_to_allocated_memory)[i * sizeof(int)];
should be
int *address = &ptr[i];
instead. (Also note the lack of superfluous parenthesizing and simpler name...)
By the way, casting malloc is harmful.
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
See the following example
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt;
Serial.println(sizeof(testInt) / sizeof(int)); // returns 3
Serial.println(sizeof(point) / sizeof(int)); // returns 1
(This is a snipplet from Arduino Code - I'm sorry, I don't "speak" real C).
The easy answer is no, you cannot. You'll probably want to keep a variable in memory which stores the amount of items in the array.
And there's a not-so-easy answer. There's a way to determine the length of an array, but for that you would have to mark the end of the array with another element, such as -1. Then just loop through it and find this element. The position of this element is the length. However, this won't work with your current code.
Pick one of the above.
Also doing an Arduino project here...
Everybody on the internet seems to insist it's impossible to do this...
and yet the oldest trick in the book seems to work just fine with null terminated arrays...
example for char pointer:
int getSize(char* ch){
int tmp=0;
while (*ch) {
*ch++;
tmp++;
}return tmp;}
magic...
You can infer the length of an array if you have an array variable.
You cannot infer the length of an array if you have just a pointer to it.
You cannot and you should not attempt deduce array length using pointer arithmetic
if in C++ use vector class
You can if you point the the whole array and NOT point to the first element like:
int testInt[3];
int (*point)[3];
point = testInt;
printf( "number elements: %lu", (unsigned long)(sizeof*point/sizeof**point) );
printf( "whole array size: %lu", (unsigned long)(sizeof*point) );
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
Technically yes, there is a way when code has a true pointer to an array as the array size is in the type as with int (*array_pointer)[3].
This differs from OP's code as the pointer point is not a pointer to an array, but a pointer to an int.
The line point = testInt; converts the array testInt to the address of the first element of the array (which is an int *) and assigns that to point. Thus the array size info is lost.
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt; // Get the address of testInt[0]
int (*array_pointer)[3] = &testInt; // Get the address of the array
printf("%zu\n", sizeof(testInt) / sizeof(int));
printf("%zu\n", sizeof(point) / sizeof(int));
printf("%zu\n", sizeof(*point) / sizeof(int));
printf("%zu\n", sizeof(*array_pointer) / sizeof(int));
printf("%p\n", (void *) testInt);
printf("%p\n", (void *) point);
printf("%p\n", (void *) array_pointer);
Sample output
3
2
1
3
0xffffcbc4
0xffffcbc4
0xffffcbc4
Pointers point and array_pointer both have values that point to the same location in memory, but the pointers differ in type.
With C99 or later that support variable length arrays, code could have been the below and achieved similar results without explicitly coding a 3 in the pointer definition.
int (*array_pointer_vla)[sizeof testInt/sizeof testInt[0]] = &testInt;
printf("%zu\n", sizeof(*array_pointer_vla) / sizeof(int));
Output
3
I see now see similarities to #user411313 answer. Perhaps the deeper explanation and VLA discussion will be useful.