comparing multidimensional arrays with sizeof() - c

I have an array made up of arbitrary length arrays.
int foo[] = {99, 1, 2};
int baz[] = {9, 8};
int tar[] = {-1, -2, -3, -4, -5, -6};
int *stuff[] = {foo, baz, tar}
I do not know the size of any of these arrays, I need to discover the size using sizeof() but I am getting strange results that do not seem to make sense when I compare them.
For example when I print the memory locations they are the same:
printf ("%p ", foo);
printf ("%p ", stuff[0]);
> 0x7ffef86f8de4 0x7ffef86f8de4
And when I print the first values of the array they are the same:
printf ("%d ", foo[0]);
printf ("%d ", stuff[0][0]);
> 99 99
However, here is the problem, when compare them with sizeof() they are NOT the same:
printf ("%lu ", sizeof(foo)/sizeof(foo[0]));
printf ("%lu ", sizeof(stuff[0])/sizeof(stuff[0][0]));
> 3 2

The problem is that you don't have an array of arrays, you have an array of pointers. So sizeof(stuff[0]) gives you the size of a pointer, not the size of the array that pointer points at. Once you convert an array to a pointer (which happens pretty much any time you use the array, since you can't really do much of anything with arrays themselves), the size of the array is lost.

Related

The result of printing an uint64_t array

I have this small piece of code:
uint64_t test[] = {1, 2, 3, 4, 5};
printf("test value: %llu\n", test);
I try to print the test array, and it gives me this number:
test value: 140732916721552
Can someone explain this and how an uint64_t array works? Thank you
In your code
uint64_t test[] = {1, 2, 3, 4, 5};
printf("test value: %llu\n", test);
%llu tells printf that it shall print a long long unsigned integer. The test part of the printf statement pass a pointer to the first element of the array to printf. In other words, there is a mismatch between what you are passing (a pointer) and what you tell printf to print (long long unsigned).
In C such a mismatch leads to "undefined behavior". So in general it's not possible to say what will be printed. Any print out will be legal from a C standard point of view. No print out would also be legal. A program crash would be legal. Anything... would be legal.
It's impossible to say what goes on in general. On a specific system, it's possible to dig into the low level things and figure out what is going on. On my system the printed value corresponds to the address of the first array element interpreted as a long long unsigned integer. But don't rely on that. Other systems may do something completely different.
The code below shows how to correctly print the address of the array and the array elements.
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
uint64_t test[] = {1, 2, 3, 4, 5};
// Print the address where the array is located
printf("Address of test value is %p\n", (void*)test);
// Print the values of the array elements
size_t sz = sizeof test / sizeof test[0];
for (size_t i = 0; i < sz; ++i)
printf("test[%zu] is %" PRIu64 "\n", i, test[i]);
return 0;
}
Output (note: address may differ in every invocation):
Address of test value is 0x7ffc4ace5730
test[0] is 1
test[1] is 2
test[2] is 3
test[3] is 4
test[4] is 5
When you define an array like this in C, what you are actually doing is storing each of these values sequentially on the stack as separate uint64_ts. The value assigned to the test identifier is then a pointer to the first of these values, a uint64_t* rather than a uint64_t. When you print test, you are printing the pointer rather than any of the elements, i.e. the memory address of the first element in your array.
The [] notation is equivalent to
*(test + i)
i.e. it dereferences a pointer to the ith element.

Populating an Array in C

I'm new to programming and am having difficulty with arrays. I've declared the array but when I go to print an element of the array I get a very different number (possibly a memory address?).
#include <stdio.h>
int main()
{
int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
printf("%d", &array[3]);
return 0
}
Then it prints 6356748 instead of "3." What am I doing wrong?
Use:
printf("%d", array[3]);
When you use &variable, it returns the address of the variable.
That's because you are printing the address:
printf("%d", &array[3]); // note the use of &
Use this to print the value:
printf("%d", array[3]); // no & used
using &array[3] you are not refearing to the value array[3] (you are using a pointer, that is a reference to an address of the memory, you will know it later). You simply need to remove the & :
printf("%d", array[3]);

How do we find the output of the following C program?

I was finding the output of the following C program, which I found on GeeksforGeeks. Here's the program:
#include <stdio.h>
void fun(int ptr[])
{
int i;
unsigned int n = sizeof(ptr)/sizeof(ptr[0]);
for (i=0; i<n; i++)
printf("%d ", ptr[i]);
}
// Driver program
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
fun(arr);
return 0;
}
The output of this code was "1 2". But according to me, the output should be just 1. Here is my interpretation of this code:
Firstly, the main function will run, in which after declaring the array "arr", next statement will execute which contains the statement fun(arr).
In that statement, the function "fun" will be called with the argument arr, which contains the address of the first element of the array.
After that, under the function fun, there is a pointer ptr as a parameter. When this function will execute, then the value of n will be calculated as 1 since here the size of ptr is 4 and the size of ptr[0] is also 4.
Next, the loop will run only once since the value of n is 1 and that's why only '1' will get printed since it is the value of ptr[0].
Please help me to find out where I am wrong.
[....] the value of n will be calculated as 1 since here the size of ptr is 4 and the size of ptr[0] is also 4.
Well, that's common, but not guaranteed.
sizeof(ptr) could very well be, result in 8, which is likely in your case, while sizeof(int) can evaluate to 4, resulting a value of 2 for n. This depends on (and varies with) your environment and used implementation.
Try printing them separately, like
printf("Pointer size :%zu\n", sizeof(ptr));
printf("Element size: %zu\n", sizeof(ptr[0]));
and see for yourself.
The size of a pointer on modern platforms is commonly either 4 or 8 bytes.
On a 32-bit platform it's likely that sizeof(ptr) == 4 and n == 1.
On a 64-bit platform it's likely that sizeof(ptr) == 8 and n == 2.

Code to print the no of elements in an array gives one less than the no of elements

I've written a code to find the number of elements in an integer array as follows:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[] = {2, 3, 5, 5};
int i;
for(i = 0; i < 4; i++)
{
printf("%d %d\n", &arr[i], arr[i]);
}
printf("%d", &arr[i - 1] - arr);
return 0;
}
The last printf prints 3 as opposed to 4 which is the number of elements in the array. Why does the code print one less than the no of elements in the array?
You pass the wrong format specifier to printf. So whatever output you get in the loop is the result of undefined behavior. To print a pointer correctly and portably you must use the %p specifier and pass a void*:
printf("%p %d\n", (void*)&arr[i], arr[i]);
The reason the last printf prints 3 (even though the format specifier is maybe wrong again), is because that's the offset between the the last cell in the array and the beginning. That's what you calculate, so remember that the last cell is indexed with offset 3.
The result of subtracting two pointers can be captured in the type ptrdiff_t. And to print that you'd need the %td format specifier, if we are to make your code more portable again:
printf("%td", &arr[i-1]-arr);
To calculate the array length, you'd need to subtract a pointer to "one passed the end" element of the array (don't worry, calculating that address is not undefined behavior) and a pointer to the beginning. Applying that to the print statement after your loop
printf("%td", (arr + i) - arr);
Which quite expectantly, is just i (4).
Your last printf need correction for specifiers as in your case the difference in first and last position address can easily fit in int but caan produce undefined behaviour so use td specifier as difference in address is of ptrdiff_t type. The problem is that how you calculate your length of array, keep in mind that indexing is done from zero that is if you have array length of 4, last index would be 3 and
array length according to your code is 3 - 0 = 3
but actually it should be 3 - 0 + 1 = 4
change your outside printf to
printf("%td",&arr[i-1] - arr + 1);
I hope this would help you. Also you printf in your for loop needs correct specifier as you are trying to print the address instead of int.

Dynamic memory allocation and sizeof()

For allocating memory to two dimensional array dynamically, I write something like this
int **ar = (int **)malloc(row*sizeof(int*));
for(i = 0; i < row; i++)
ar[i] = (int*)malloc(col*sizeof(int));
I came across this code which does the same but i cannot understand the declaration.
double (*buf)[2] = (double (*)[2])malloc(count*sizeof(double [2]));// Explain this
printf("%d, %d, %d, %d \n",sizeof(double));
printf(" %d",sizeof(buf[0]));
printf(" %d", sizeof(buf));
//prints 8, 16, 16, 4 when count is 3
The output of first printf() is trivial. Please help me with the next two.
double (*buf)[2] = (double (*)[2])malloc(count*sizeof(double [2]));// Explain this
This
double (*buf)[2]
defines buf to be a pointer to an array of 2 doubles.
This
(double (*)[2])malloc(count*sizeof(double [2]));
can (and shall) be rewritten as
malloc(count * sizeof(double [2]));
The above line allocates memory with the size of count times "size for an array of 2 doubles".
This
=
assigns the latter to the former.
It all ends up with buf pointing to an array of count * 2 doubles.
Access its elements like this
(*buf)[0][0];
Note that this approach creates a pointer to a "linear" array, that is an array where all elements are store in one continues block of memory.
Whereas the approch you 1st mention in you question creates a "scattered" array that is an array where each row might be located in a seperate block of memory.
This
printf("%d, %d, %d, %d \n",sizeof(double));
provokes undefined behaviour, as from its 1st (format) parameter the printf expects four addtional parameters and is being passed only one.
The size of a double typically is 8.
This
printf(" %d",sizeof(buf[0]));
prints the size of the first element that buf points to. As buf points to an array of 2 doubles, it is expected to print 2 times "size of a double" which 2 * 8 = 16.
This
printf(" %d", sizeof(buf));
prints the size of buf. As buf is defined as a pointer, the size of a pointer on is printed. This typically is 4 for a 32bit implementation and 8 for 64bit implementation.
Note: The value of count does not appear in any of the sizes printed above, not directly, nor indireclty, as In C it is not possible to derive from a pointer how much memory had been allocated to it.

Resources