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.
Related
The code goes
#include<stdio.h>
int sumOfElements_new(int *A, int size){ // int *A or int A[] same thing
int i, sum = 0; // remember arrays decay as pointers in other functions besides main
for (i =0; i<size;i++){
sum += A[i]; // A[i] = *(A+i)-> value at that address
}
return sum;
}
int main(){
int A[] = {1,2,3,4,5};
int size = sizeof(A)/sizeof(A[0]);
int total = sumOfElements_new(&A[0], size);
printf("%d\n", &A[4]);
printf("Sum of elements = %d\n", total);
printf("Size of A = %d and size of A[0] = %d\n", sizeof(A), sizeof(A[0]));
return 0;
}
Now when I do something like this
int total = sumOfElements_new(&A[3], size);
the result is
Sum of elements = 30
Size of A = 20 and size of A[0] = 4
whenever I use &A[1] to any &A[6], it gives me different values.
Then why calling it in
int size = sizeof(A)/sizeof(A[0]);
gives me the correct answer of the Sum of the elements but, using &A[1-6] the answer goes up and its not even memory address??
Given how you define size, (e.g) int size = sizeof(A)/sizeof(A[0]); you can [only] do:
sumOfElements_new(&A[0],size)
If you use (e.g.) &A[3], you can't pass:
sumOfElements_new(&A[3],size)
because you're telling the function to sum past the end of the array. This is UB (undefined behavior). The program will fetch the data beyond the end, but that data is random (it is just whatever happens to be there).
You have to shorten the size/length you pass to the function. What you'd want is:
sumOfElements_new(&A[3],size - 3)
UPDATE:
May want to comment on printf("%d\n", &A[4]); as well..
This presents another issue. You [probably] want to print the value of the element of the A that has index 4.
The indexing is correct (i.e. it does not go beyond the end of the array), but you're passing the address of that element and not its value.
With your original code, if you compiled with warnings enabled (e.g. using the -Wall option--which you should always do, IMO), the compiler would flag this statement.
That's because you're passing an address [which on modern x86 cpus is probably 64 bits]. That's an unsigned quantity and you're trying to print it in decimal using only 32 bits [because an int is usually only 32 bits].
So, to print the value, you'd probably want:
printf("%d\n", A[4]);
If you truly wanted to print the address of that element [a more advanced usage], you could do:
printf("%p\n", &A[4]);
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.
I wrote two functions and call the functions in main.
Function 1 – I wrote a function that returns void and takes an int * (pointer to integer array) or int[], and int (for the size). The function needs to initialize all the elements of the array to non-zero values.
Function 2 – I wrote another function that returns int and takes an const int * (pointer to integer array) or int[], and int (for the size). The function should sum all the elements of the array and return the sum.
In main I defined an integer array of size 5. Called function 1 in main to initialize the values of the array. Called function 2 in main to get the sum and print the value of the sum to the console.
My problem is the program runs but the print out for sum we are getting is a large (in the millions), random, number and is not the expected answer of 15. Anyone who can help us get the correct answer would be greatly appreciated
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma warning(disable: 4996)
void func1(int* ptr, int size);
int func2(const int* ptr, int size);
int main()
{
int grid[5];
func1(grid, 5);
func2(grid, 5);
}
void func1(int* ptr, int size)
{
*ptr = 1, 2, 3, 4, 5;
}
int func2(const int* ptr, int size)
{
int sum;
sum = ptr[0] + ptr[1] + ptr[2] + ptr[3] + ptr[4]; // *(ptr + 0); putting an asterisk makes it so that it changes the entire "ptr" value and the "[0]" value
printf("\n\nThe sum of the integers in the array is %d.\n\n", &sum);
}
*ptr = 1, 2, 3, 4, 5;
does not do what you think it does. It actually evaluates all the integer constants but sets ptr[0] to be 1 (see comma operator for more detail), leaving all the others at some arbitrary value.
Note that it is not evaluating *ptr = (1, 2, 3, 4, 5) (which would set *ptr to 5) but is actually evaluating (*ptr = 1), 2, 3, 4, 5 - this works because something like 42 is actually a valid C statement, albeit not very useful.
If you're trying to set the array to increasing values, just use something like:
for (int i = 0; i < size; i++)
ptr[i] = i + 1;
You probably also want to do that when summing the values since it should depend on the passed-in size rather than just summing five values:
int sum = 0;
for (int i = 0; i < size; i++)
sum += ptr[i];
Additionally, the value you are printing out is not the sum, it's the address of the variable containing the sum (a decent compiler will warn you about this). You should be using sum in your printf rather than &sum.
And, as a final note, the signature for func2 indicates that you should actually be returning the sum rather than just printing it. So I would suggest removing the printf from that function and simply doing:
return sum;
Then you can put the printf into the caller (main) as follows:
int main(void)
{
int grid[5];
func1(grid, sizeof(grid) / sizeof(*grid));
int sum = func2(grid, sizeof(grid) / sizeof(*grid));
printf("The sum of the integers in the array is %d.\n\n", sum);
return 0;
}
Note the use of sizeof(grid) / sizeof(*grid), which is basically the number of array elements in grid - this will allow you to resize grid by simply changing it in one place to something like int grid[42] and still have all the code work with the updated size.
Not actually necessary for your code but it's best to get into good programming habits early (more descriptive names for your functions may also be a good idea).
Line *ptr = 1, 2, 3, 4, 5; assigns ptr[0] value and leaves other spots unitilized so when you sum it, it will be random memory.
You should use for like this to initialize
for(int i=0;i<size;i++)
{
ptr[i] = i+1;
}
and similiar aproach to sum it.
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.
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.