I write this code and the output was like this B C D E
char a[5] = {'A' , 'B' , 'C' , 'D'};
char *b = a + 2;
int i = 0 ;
for(i = 0 ; i < 4 ; i ++)
{
*b = (a[i] + 1);
printf("%c",*b);
}
But when I add reference like this :
char a[5] = {'A' , 'B' , 'C' , 'D'};
char *b = &a + 2;
int i = 0 ;
for(i = 0 ; i < 4 ; i ++)
{
*b = (a[i] + 1);
printf("%c",*b);
}
the output become just B.
This has to do with how pointer arithmetic is done. When you add a value to a pointer, it increments the pointer by that value times the size of the type it references.
In the expression a + 2, a has type char *, so adding 2 increases the address by 2 * sizeof(char) == 2 bytes.
Given &a + 2, &a has type char (*)[5], i.e. a pointer to an array of 5 char. Adding 2 to this increases the address by 2 * sizeof(char [5]) == 10 bytes. This points to a memory location past the end of the array, so dereferencing it invokes undefined behavior, which in this cases leads to the loop exiting early.
You also have an invalid assignment in the second case, as you're trying to assign a value of type char (*)[5] to a value of type char *.
Compiler should report error on
char a[5] = {'A' , 'B' , 'C' , 'D'};
char *b = &a + 2; // <<< compile error
int i = 0 ;
for(i = 0 ; i < 4 ; i ++)
{
*b = (a[i] + 1);
printf("%c",*b);
}
and if you remove the line that generates compile error, the output should be no difference from your first piece of code.
Related
I am trying to print a 2-D array in C by using pointers but I am not getting the expected output.
Program:-
#include <stdio.h>
int main()
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p;
for ( p = arr; p <= arr+6; p++)
{
printf("%d ", *p);
}
return 0;
}
Output:-
1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463
Could you tell me where I am wrong as the output should only be:
1 2 3 4 5 6
Could you tell me where I am wrong
The elements of arr are not integers, but arrays of 3 integers. So arr+6 is surely a different address than what you expect, since pointer arithmetic works in multiples of the size of the type in the array.
You'll always be better off using nested loops to iterate over a multidimensional array; treating it as one single-dimensional array of int leads to exactly the kinds of confusion you see here. The code is harder to understand and verify, it won't be any slower.
First, when looping through arrays of size n wth an index i, the condition for continuation should be i < n rather than i <= n, because array indexes in C run from 0 through n-1.
However, your code has a more serious error: 1-dimensional arrays can be 'decayed' into pointers to the elements' type; however, 2-dimensional arrays decay into pointers to 1-dimensional arrays. So, in your case, the type of the pointer used in the arr + 6 expression is a pointer to an array of three integers; further, when the 6 is added, that operation is performed in terms of the size of the pointed-to object, which is sizeof(int) * 3 – so, even when changing the <= to <, you will be running far beyond the actual bounds of the array.
To make the pointer arithmetic work in the correct 'units' (i.e. sizeof(int)), cast the arr to an int* before the addition (and also change the <= to <):
#include <stdio.h>
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int* p;
for (p = (int*)arr; p < (int*)arr + 6; p++) {
printf("%d ", *p);
}
return 0;
}
You are trying to access the value in the wrong way, The two-dimensional array is saved as a continuous block in the memory. So, if we increment the value of ptr by 1 we will move to the next block in the allocated memory.
int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;
int i,j;
for (i = 0; i < 6; i++) {
printf("%d ", *(ptr + i));
}
return 0;
Array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements.
The type of the array elements of this array
int arr[2][3];
is int [3]. So a pointer to the first element of the array has the type int ( * )[3].
This assignment
p = arr;
where p has the type int * is incorrect because the operands of the assignment have incompatible pointer types.
At least you need to cast the right expression to the type int * like
p = ( int * )arr;
The same casting you need to use in the condition in the for loop. That is instead of
p <= arr+6
you have to write
p < ( int * )arr+6
Below there is a demonstration program that shows how to output a two-dimensional array as a two-dimensional array using pointers.
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int ( *p )[3] = arr; p != arr + 2; p++ )
{
for ( int *q = *p; q != *p + 3; ++q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
return 0;
}
If you want to output the two-dimensional array as a one-dimensional array then you can write
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int *p = ( int * )arr; p != ( int * )arr + 6; p++ )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
In
for ( p = arr; p <= arr+6; p++)
the expression arr, as an rvalue, is a pointer to the first element of the array (which is of type int [3], so each time you increment that pointer, it moves three int positions forward ---a whole row---, and so, arr + 6 points just after the sixth row of the array (if the array should ever had six rows) You can do it (with the proper explicit pointer conversions, as you are mixing pointers to int with pointers to int [3]) with the expression arr + 2 which is the addres of the first array element after the second row (and the number of rows of the array).
You can do it also declaring
int (*aux)[2][3] = &arr; /* aux is a pointer to the whole 3x2 array,
* so aux + 1 will be the position of the second
* 2D array after this one */
and then
int *end = (int *)(aux + 1);
or simply
int *end = (int *)(&arr + 1); /* see below */
(Beware that arr and &arr are both pointers and point to the same place, but they are not the same type (arr is of type int (*)[3] and &arr is of type int(*)[2][3])
So let's rewrite your code as
for (p = (int *)arr; p < end; p++)
or
for (p = (int *)arr; p < (int *)&arr + 1; p++)
would work, which seems more natural to do the calculus in complete array units than in rows or single cells (and you can change freely the dimensions of the array)
Your code would be:
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *end = (int *)(&arr + 1); /* try to avoid evaluating this expression in the loop
* despite that it can be optimized to comparing
* with a constant value */
char *sep = "";
for (int *p = (int *)arr; p < end; p++)
{
printf("%s%d", sep, *p);
sep = ", ";
}
putchar('\n');
return 0;
}
(Beware that you have to use < operator and not <= as you don't want to print the value pointed by end, because it lies one place outside of the array)
Finally a note: this will work with true arrays, but not with function parameters declared as arrays, because they decay to pointers and then &arr is not a pointer to data the size of the array, but it is the address of the parameter itself, which points to the array somewhere else.
I don't understand why the code below changes the array b:
int a[] = { 3, 6, 9 };
int b[] = { 2, 4, 6, 8, 10 };
int **c;
int **d[2];
c = (int **)malloc (b[1] * sizeof(int *));
*c = &a[1];
c[1] = c[0] + 1;
*d = c;
c = c + 2;
*c = b;
c[1] = &c[0][3];
*(d + 1) = c;
d[0][3][1] = d[1][0][0];
d[1][0][2] = d[0][1][0];
I have run this code and found the values of array a and array b but I am unable to understand how these values come.
Array a remains unchanged while b becomes 2, 4, 9, 8, 2. How does this happen?
c = (int**)malloc(b[1] * sizeof(int*)); //int **c[4] ???
c is an array of double pointers *c = &a[1] this means that c[0] has the address of array a's second index. I am not getting the way to interpret this.
The code contains actual statements, therefore it must be part of a function body, hence all declarations herein have automatic storage. It is highly convoluted, with purposely contrived double indirections... Lets analyse it one line at a time:
int a[] = { 3, 6, 9 }; -- a is an array of 3 ints initialized with some explicit values.
int b[] = { 2, 4, 6, 8, 10 }; -- likewise, b is an array of 3 ints initialized with some explicit values.
int **c; -- c is an uninitialized pointer to a pointer to int, that can be made to point to an array of pointers to int.
int **d[2]; -- d is an uninitialized array of 2 pointers to pointers to int, each of which can be made to point to an array of pointers to int.
c = (int **)malloc(b[1] * sizeof(int *)); -- c is set to point to a block of uninitialized memory with a size of 4 pointers to int. In short, c now points to an uninitialized array of 4 pointers to int.
*c = &a[1]; -- The element pointed to by c (aka A[0]) is set to point to the second element of a (aka a[1], with a value of 6). The value of A[0] is &a[1].
c[1] = c[0] + 1; -- The second element in the array pointed to by c (aka A[1]) is set to point to the element after the one pointed to by c[0], hence it points to the third element of a (aka a[2] with a value of 9). The value of A[1] is&a[2]`.
*d = c; -- The first element of d is set to the value of pointer c, which is the address of A[0]. The value of d[0] is &A[0].
c = c + 2; -- The pointer c is incremented by 2, it now points to the third element of the array A allocated with malloc(), A[2].
*c = b; -- The element pointed to by c, A[2], which is itself a pointer, is set to point to the first element of b, b[0]. The value of A[2] is &b[0].
c[1] = &c[0][3]; -- The element after that, A[3], the 4th element of the array allocated by malloc, is set to point to the 4th element of the array pointed to by the element c points to. &c[0][3] is equivalent to c[0] + 3 or &(*c)[3] or simply *c + 3. This element is b[3] which has the value 8. The value of A[3] is&b[3]`.
*(d + 1) = c; -- This is equivalent to d[1] = c; which sets the second element of d to the value of the pointer c, which is the address of the 3rd element of the array allocated wth malloc(), A[2], which points to b[0]. The value of d[1] is &A[2].
d[0][3][1] = d[1][0][0]; -- Let's rewrite these terms:
d[0][3][1] => (&A[0])[3][1] => A[3][1] => (&b[3])[1] => *((b + 3) + 1) => b[4]
d[1][0][0] => (&A[2])[0][0] => (*&A[2])[0] => A[2][0] => (&b[0])[0] => b[0] which is the value 2.
Hence b[4] = 2;.
d[1][0][2] = d[0][1][0]; -- Let's rewrite these:
d[1][0][2] => (&A[2])[0][2] => (*&A[2])[2] => A[2][2] => (&b[0])[2] => (b + 0)[2] => b[2].
d[0][1][0] => (&A[0])[1][0], ie A[1][0] => (&a[2])[0] => *&a[2] => a[2] that has a value of 9.
Hence b[2] = 9;
As a consequence, the array b now has elements { 2, 4, 9, 8, 2 }.
You can run the program:
#include <stdio.h>
#include <stdlib.h>
int main() {
int a[] = { 3, 6, 9 };
int b[] = { 2, 4, 6, 8, 10 };
int **c;
int **d[2];
c = (int **)malloc (b[1] * sizeof(int *));
*c = &a[1];
c[1] = c[0] + 1;
*d = c;
c = c + 2;
*c = b;
c[1] = &c[0][3];
*(d + 1) = c;
d[0][3][1] = d[1][0][0];
d[1][0][2] = d[0][1][0];
printf("a = { ");
for (size_t i = 0; i < sizeof a / sizeof *a; i++)
printf("%d, ", a[i]);
printf("};\n");
printf("b = { ");
for (size_t i = 0; i < sizeof b / sizeof *b; i++)
printf("%d, ", b[i]);
printf("};\n");
return 0;
}
I'm trying to pass the address of a 2D array to a function in C. I initialize the 2D array as:
const int N = 3;
char t[N][N];
I try to convert this into a char***:
char*** t_ptr = &t;
But it fails with a:
warning: initialization from incompatible pointer type
The function I want to receive the array has a prototype such as:
void f(char*** t, int N) { ... };
What am I doing wrong? Thank you.
This
char*** t_ptr = &t;
is wrong as compiler pointed because t is an two dimensional array, instead of triple pointer like char*** use pointer to an array to point to it. For e.g
char t[3][3] = { "ab","de","gh"}; /* total 3 1D array & each 1D array has 3 elements */
char (*t_ptr)[3] = t; /* t_ptr is a pointer to an array, pointing to 3 elements at a time */
And you can print t_ptr like
for(int index = 0; index < 3 ; index++) {
printf("%s\n",t_ptr[index]);
}
For reading c declarations, you can visit: https://cdecl.org/
Now using #Achal's example array:
#include <stdio.h>
#include <stdlib.h>
int main()
{
// t is a 2D array (not a VLA)
char t[3][3] =
{
{'a', 'b', '\0'},
{'d', 'e', '\0'},
{'g', 'h', '\0'}
};
printf("t is composed of 3 arrays of 3 characters each,\n");
printf("with the following addresses (on my machine):\n");
printf("--------------------------------------------------\n");
printf("%p, %p, %p\n", t[0], t[1], t[2]);
// ------------------------------------------------
// p is an array of 3 char pointers or char*
// Notice initialization
char* p[3] = {t[0], t[1], t[2]};
// following line of code will break, if no '\0' is encountered
// since %s requires a char* and a null terminator
printf("\nPrint strings using p:\n");
printf("------------------------\n");
printf("%s, %s, %s\n", *p, *(p + 1), *(p + 2));
// ------------------------------------------------
// q is a pointer to a char* or q has type char**
// Notice initialization of q (q points to p)
char** q = p;
printf("\nUsing q:\n");
printf("-----------\n");
printf("%s, %s, %s\n", *q, *(q + 1), *(q + 2));
// ---------------- printing characters individually
printf("\nIndividually:\n");
printf("---------------\n");
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
printf("%c ",
*(*(q + i) + j)
);
}
printf("\n");
}
// -----------------------------------------------
// r is a pointer to an array of size 3 containing char
// r advances three char at a time (r doesn't know the size of t)
char (*r)[3] = t; // this is the type of t
printf("\nUsing r:\n");
printf("---------------\n");
printf("%p, %p, %p\n", *r, *(r + 1), *(r + 2));
// to extract chars
printf("%c, %c", *(*(r + 0) + 0), *(*(r + 2) + 1));
// -----------------------------------------------
return EXIT_SUCCESS;
}
Output:
t is composed of 3 arrays of 3 characters each,
with the following addresses (on my machine):
--------------------------------------------------
000000000022FE2F, 000000000022FE32, 000000000022FE35
Print strings using p:
------------------------
ab, de, gh
Using q:
-----------
ab, de, gh
Individually:
---------------
a b
d e
Using r:
---------------
000000000022FE2F, 000000000022FE32, 000000000022FE35
a, h
Process returned 0 (0x0) execution time : -0.000 s
Press any key to continue.
char t[N][N];
is in fact the same as
char t[N * N];
in memory. A pointer to such an array would in both cases be of type char *.
char *** is a pointer to a pointer, that is a pointer to a char, whereas char * is a pointer to a char and that's how you pass array references in C: You pass them as a pointer to the first element of that array and this first element is a char.
C cannot retain the exact type or structure of an array as soon as you pass it to functions. In memory, a char array is just a bunch of memory filled with chars and all you can pass around is a pointer to that memory. If that memory is char [] or char [][] or even char [][][] plays no role, in memory all three are a block full of chars and the function would have to explicitly know the structure in memory, otherwise all char arrays will always be char [] for a function.
I strongly discourage C beginners to ever use multidimensional arrays. Instead of
char t[N][N];
char c = t[y1][x1];
t[y2][x2] = 'X';
use
char t[N];
char c = t[y1 * N + x1];
t[y2 * N + x2] = 'X';
As that's basically what the compiler will internally do anyway.
Note that multidimensional arrays in C are not x-y, but y-x, the first value is the row, the second on the column, please see this tutorial.
Whoever disbelieves what I just said, try out this code:
int main ( ) {
char a[5][5];
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
a[y][x] = x + 10 * y;
}
}
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
printf("%02d ", a[y][x]);
}
printf("\n");
}
printf("------\n");
char * a2 = (char *)a;
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
printf("%02d ", a2[y * 5 + x]);
}
printf("\n");
}
}
You can run it online, if you like, the output is identical. Also have a look at the assembly code the compiler generates for either loop (e.g. gcc -S) and you will see it's almost identical as even in the first case the compiler uses an add and a mul instruction to access the correct memory location within the array.
I'm working on a C program and i am struggling with it (I've been spoiled by the concept of object orientation).
What i want to do is this:
I want to put values in a char array into an int. So for example i have char[0] == '1' and char[1] == '2'. I want to put these values in an int variable so its value is 12. I have tried looking but I am not sure how to get this done.
I really am poor at explaining so please ask for more info if necessary.
If your char array is made with characters '1' and '2':
char a[2];
a[0] = '1';
a[1] = '2';
int b = (a[0]-'0')*10 + (a[1]-'0');
If your char array is made with numbers 1 and 2:
char a[2];
a[0] = 1;
a[1] = 2;
int b = a[0] * 10 + a[1];
also, see: Why does subtracting '0' in C result in the number that the char is representing?
If the character array contains a string that is if it is zero-terminated then you can apply standard C function atoi declared in header <stdlib.h>.
For example
char s[] = "12";
int x = atoi( s );
If the array is not zero-terminated as
char s[2] = "12";
then you can convert its content to an integer manually.
For example
int x = 0;
for ( size_t i = 0; i < sizeof( s ) / sizeof( *s ); i++ )
{
x = 10 * x + s[i] - '0';
}
What you are trying to do is called parsing. In c this can be done with the atoi() function like this:
char s[] = "12";
int num = atoi(s);
I have a doubt in pointers manipulation...
main()
{ int x=10; // extra line added...
char *p=x;
printf("%d", &p)
printf("%d", &p[0]);
printf("%d" , &p[1]);
}
This code gives output
Address of 10..
10
11
how are the last two outputs are coming.. Can anyone explain it to me ..?
Code changed.....
This is Undefined Behavior.
The pointer needs to point to something valid before some value can be added to that location.
char a = 10;
char *p = &a;
Will explain two scenarios:
Scenario 1: char * p = x;
x == 10, p is a char pointer which is initialized with 10 (an address which user program can't access): p == 10
The value of p (ie, *p) will lead to segmentation fault (being invalid memory reference)
p[0] == *(p + 0) and &p[0] == (p+0) == p which is 10.
Hence printf("%p", &p[0]) will give you 10.
p[1] == *(p + 1) and &p[1] == (p+1)
Since, p is a character pointer, it gets increments by sizeof(char), ie 1
Hence printf("%p", &p[1]) will give you 10+1 = 11
Scenario 2: char * p = &x;
Here p is a char pointer pointing to integer x
Value of x = 10
Address of x = 1000 (assume)
Hence p = 1000
p[0] == *(p + 0) and &p[0] == (p+0) == p
Hence printf("%p", &p[0]) will give you 1000
p[1] == *(p + 1) and &p[1] == (p+1)
Since, p is a character pointer, it gets increments by sizeof(char), ie 1
ie &p[1] == 1000+1 == 1001
p and &p[0] will be evaluated to same address (address of first element of array) which is 10.
So &p[0] will be evaluated to 10 and &p[1] to &p[0] + sizeof(char) which is 11
Your code will most likely segfault though when you dereference p (*p).
Following code will always print True.
main()
{
int* p;
printf("%s\n",p == &p[0] ? "True" : "False");
}
Some errors in your code:
int x = 10;
char * p = &x; // error 1 - you was assigning int to pointer
printf("%p\n", &p); // error 2 - you printing address of pointer (char **),
// so different format string is needed
printf("%p\n", &p[0]); // same error 2 - printing address of first byte in int x
printf("%p\n" , &p[1]); // same error 2 - printing address of second byte in int x
printf("%d", &p[0]);
printf("%d" , &p[1]);
it will print out the address that p is pointered on..
because char *p=x; while x = 10;
then ,, &p[0] = 10, &p[1] = 11 &p[2] = 12 , and so on..
printf("%d", &p);
I'm not so sure about this, but as i know it will print out the value contained in memory 10 in my case = 10000
printf("%d", p);
it will print out the 10, which is the *p value;
cmiiw
char *p=10;
The code at present has undefined behavior. Pointer p is not pointing to any valid memory location to initialize 10 in that location.
With that said, both p, &p[0] yields the same memory location.