Pointer not printing in the desired way - c

This is a C code
int (*a)[3];
a is a pointer to an array of 3 integers
a=(int (*)[3])malloc(sizeof(int)*3);
note the Typecast used here; the number of elements must be specified in the typecast shown. Also, the brackets around the * is necessary.
printf("brrbrrbrr %d %d %d %d\n",&a,a,a+1,a+2);
*(a+0)[0]=40;
*(a+0)[1]=41;
*(a+0)[2]=42;
printf("noobnoob %d %d %d \n",a[0][0],*(a+0)[1],(*(*(a+0)+2)));
The output is:
brrbrrbrr -7077000 29278656 29278668 29278680
noobnoob 40 41 0
I am not getting why the last number is 0 instead of 42?

Indexation has higher precedence than dereferencing a pointer. Your assignments don't do what you want. They are evaluated like:
*((a+0)[0])=40;
*((a+0)[1])=41;
*((a+0)[2])=42;
If you want to keep your syntax, you shall use parenthesis like:
(*(a+0))[0] = 40;
(*(a+0))[1] = 41;
(*(a+0))[2] = 42;
The same applies for printing the second element of the array. *(a+0)[1] shall be (*(a+0))[1].

What you are looking for is
int (*a)[3] = malloc(sizeof(int) *3);
(*a)[0] = 40;
(*a)[1] = 41;
(*a)[2] = 42;
printf("%d %d %d\n",(*a)[0],(*a)[1],(*a)[2]);
a is a pointer to an array of 3 int members. So allocate memory for the pointer and store values as shown above.
If you want the address of where the values are stored then you should do
printf("%p\n",(void*)(a)[0]);

Related

Determinant of the matrix — recursive function

I wrote a program which returns a determinant of a matrix. I have a problem, actually; it always returns the "0" value. I notice that my determinant always stays as 0 even though I add numbers to it.
I wrote an English translation in the comments to understand my program better. I use a method in which we select one number and then crossed the element from the column and line of the selected number and then calculate the determinant of the uncrossed elements.
#include<stdio.h>
#include<stdlib.h>
float wznmacierz(float*macierz, int rozmiar)/*"macierz" means a matrix and "rozmiar" is a size of matrix */
{
if (rozmiar == 1)
return *macierz;
float *podmacierz = malloc((rozmiar-1)*(rozmiar-1)*sizeof(float)); // making a second matrix for uncrossed elements.
int wyznacznik = 0; // wyznacznik is the determinant of matrix
for(int element_S = 0; element_S <rozmiar; element_S++) //element s is a number from first line
{
for (int w = 1 ; w < rozmiar; w++ ) //line of checking element
{
for(int kolumna = 0; kolumna < rozmiar; kolumna++)//column of chcecking element
{
if(kolumna == element_S)
continue;
*podmacierz = macierz[(rozmiar*w)+(kolumna)];
podmacierz++;
}
}
wyznacznik += macierz[element_S]*( element_S % 2 ? -1: 1)* wznmacierz(podmacierz, rozmiar-1);
}
return wyznacznik;
}
void main()
{
float a[2][2]={{1,3},{9,8}};
printf("%d", wznmacierz(a,2));
}
Change void main to int main, because main returns an int.
In printf("%d", wznmacierz(a,2)); , change %d to %g, because %d is for formatting an int, but wznmacierz returns a float. %g will format a float. Also add \n after %g to complete the line being output.
In printf("%d", wznmacierz(a,2));, change a to *a because wzmacierz expects a pointer to a float, not a pointer to an array of float. This is a kludge to get your program “working” quickly; see Notes below.
You cannot use podmacierz both to hold the start address of the allocated array and to increment to places within the array. Inside the loop on element_S, put float *p = podmacierz; to make a second pointer, and change the uses of podmacierz inside that loop to p.
Before returning from the function, use free(podmacierz); to release the allocated space.
Notes
In main, a is declared as float a[2][2]. This makes it an array of 2 arrays of 2 float. In the call wznmacierz(a,2), a is automatically converted to a pointer to its first element. That produces a pointer to an array of 2 float. However, wznmacierz is declared with a parameter float*macierz, which is a pointer to a float.
One way to fix this is to pass *a. Once a is converted to a pointer to its first element, a pointer to an array of float, then applying * produces the thing that pointer points to, an array of float. Then that array of float is automatically converted to a pointer to its first element, producing a pointer to a float. You could also write wznmacierz(&a[0][0], 2).
This produces a pointer of the correct type for wznmacierz, which then access the array by calculating element locations, using macierz[(rozmiar*w)+(kolumna)]. This nominally calculates correct addresses for the array elements, since arrays are laid out in memory contiguously, but it is bad style unless necessary, and some people might consider it not to conform to the C standard in a pedantic sense.
One fix would be to define a in main as float a[2*2] = {1, 3, 9, 8};. Then the matrix is implemented as single flat array of float everywhere it is used.
Another fix would be to upgrade wznmarcierz to use two-dimensional arrays. A number of changes are needed to do this. I have not tested them, but I think they are at least:
Change wznmacierz(a,2) to wznmacierz(2, a).
Change the declaration of wznmacierz to float wznmacierz(int rozmiar, float macierz[rozmiar][rozmiar]).
Change the use of macierz inside the function from macierz[(rozmiar*w)+(kolumna)] to macierz[w][kolumna].
Change float *podmacierz = malloc((rozmiar-1)*(rozmiar-1)*sizeof(float)); to float (*podmacierz)[rozmiar-1] = malloc((rozmiar-1) * sizeof *podmacierz);.
Remove the float *p = podmaciarz; that I told you to insert above.
Inside the loop using w, insert float *p = podmacierz[w];.
Change macierz[element_S] to macierz[0][element_S].
Change wznmacierz(podmacierz, rozmiar-1) to wznmacierz(rozmiar-1, podmacierz).

why a array-pointer gives me different values

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]);

Different types and sizes for each row of a 2D array in C

I'm trying to write a 2D array where each row has a different datatype and a different number of cells.
The first row contains 3 chars, whereas the second row contains 2 ints.
The function "copy" should copy byte-by-byte the array po into the row-array p[1], but the visualization shows -24 3 instead of 1000 2000 (see picture). What is the solution? Thanks.
#include <stdio.h>
#include <stdio.h>
void copy(char* dest,char* source,int dim) {
int i;
for(i=0; i<dim ;i++)
dest[i]=source[i];
}
int main(void) {
char **p;
int po[]={1000,2000};
p = (char**) calloc(2,sizeof(char*));
p[0]= (char*) calloc(3,sizeof(char));
p[1]= (char*) calloc(2,sizeof(int));
p[0][0]='A';p[0][1]='B';p[0][2]='C';
copy((char*) p[1],(char*) po,2*sizeof(int));
printf("%c ",p[0][0]); printf("%c ",p[0][1]); printf("%c \n",p[0][2]);
printf("%i ",p[1][0]); printf("%i \n",p[1][1]);
free(p[1]);free(p[0]);free(p);
return 0;
}
1000 is represented in binary as 1111101000. Since int takes 2 bytes that means with 16 bits the actual representation should be 00000011 11101000 . Although it might appear so, the actual storage in the memory happens like this.
11101000 00000011
Now this is really weird, I know. But many of the machines follow little-endian convention, which means that
Whenever a multibyte value is stored, the first byte of the memory stores the least significant byte of the value.
I know this is weird, but it is very helpful to follow little-endian over big-endian(which obviously means the other way round) in implementing many algorithms.
Hence clearly 11101000 means -24 and 00000011 means 3. And there is no discussion about the 2000 at all because you are only asking for 2 characters and then converting them to integers using %i.
Now, that being said, I appreciate your curiosity and experimenting nature. But if you wanted what you expect to happen, the right piece of code would be
printf("%i ",((int*)p[1])[0]);
printf("%i \n",((int*)p[1])[1]);
And about how you wanted to have different datatypes in a single 2-D array, it is not technically possible. But as you have already guessed, you can store all addresses in a char*, that is true. But then like how I did above,
you will have to cast every array to its true form. For that purpose, you will have to store the datatype of every row in some other form.(Maybe in an int array, by putting 0 for int, 1 for char, 2 for double etc).
Try this for the second line of printf:
printf("%d %d \n", ((int *)p[1])[0], ((int *)p[1])[1]);
p[1][1] is the second byte (char) in array of chars. You want to access second int in array of ints. For that reason you have to convert p[1] to int * array and then get the element. For better readability:
int * p_int = (int *)p[1];
printf("%d %d \n", p_int[0], p_int[1]);
I'm trying to write a 2D array where each row has a different datatype
That's not going to work. By definition all elements of an array are the same type. You can't have some elements be one type and some be a different type.
If p has type char **, then p[i] has type char *, and p[i][j] has type char. In the call
printf( "%i", p[1][0] );
it's treating p[1][0] as a char object, not an int object, and thus only looking at part of the value. You could do something like
printf( "%i", *((int *)&p[1][0]) );
that is, treat the address of p[1][0] as the address of an int object and dereference it, which is ... well, pretty eye-stabby, and prone to error.
A better option would be to create an array of union type where each member can store either a char or int value, like so:
union e { char c; int i };
union e **p = malloc( 2 * sizeof *p );
p[0] = malloc( 3 * sizeof *p[0] );
p[1] = malloc( 2 * sizeof *p[1] );
p[0][0].c = 'A'; p[0][1].c = 'B'; p[0][2].c = 'C';
p[1][0].i = 1000; p[1][1].i = 2000;
printf( "%c\n", p[0][0].c );
printf( "%i\n", p[1][0].i );
There's no good way to specify "this entire row must store char values, while that entire row must store int values" - you'll have to enforce that rule yourself.

Why is my empty int array not returning 0 for the last index in C?

int *ar[3];
int x;
for (x == 0; x < 3; ++x)
printf("AR[%d]: %d\n", x, ar[x]);
this returns
AR[0]: 0
AR[1]: 0
AR[2]: 4196432
"int *ar[3]" means array of pointers, its element is a pointer to int, and there is no assignment for this array, that means its element might be any garbage. BTW, the type of ar[x] is pointer, if you want to print ar[x], you should use "%p" instead of "%d", otherwise there is a vast from %p to %d, and the value maybe is not you expect.

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