Trying to load an array using pointers in C - c

I am trying to load an array using pointers. I am assigned my x[0] the value of 2, and the desired output is 2, 4, 8, 16, 32, 64, 128.
For some reason, my loop starts at index 4 or it starts at index 2 and only prints 2, 4, 8, 16.
#include <stdio.h>
#include <math.h>
int main() {
int x[7] = {}, *ip;
ip = &(x[0]);
*ip = 2;
for(int i = 0; *ip < sizeof x; *ip *= 2) {
printf("value of x: %d\n", x[i]);
}
}

This loop:
for(int i = 0; *ip < sizeof x; *ip *= 2) {
printf("value of x: %d\n", x[i]);
}
will print x[i] till the value at memory location pointed by pointer ip is less than the size of object x in bytes. Note that i is initialised with 0 but it is nowhere altered.
Assume that size of int on your system is 4 bytes, the sizeof x will yield 28 because x is an array of 7 integers (7 * 4 = 28).
Iteration I:
i = 0 //initialized
*ip = 2, 2 < 28 ----> true
print x[0] ----> 2
*ip *= 2 ----> *ip = 4
Iteration II:
*ip = 4, 4 < 28 ----> true
print x[0] ----> 4
*ip *= 2 ----> *ip = 8
Iteration III:
*ip = 8, 8 < 28 ----> true
print x[0] ----> 8
*ip *= 2 ----> *ip = 16
Iteration IV:
*ip = 16, 16 < 28 ----> true
print x[0] ----> 16
*ip *= 2 ----> *ip = 32
Iteration V:
*ip = 32, 32 < 28 ----> false
loop exits
Hence, you are getting output - 2, 4, 8, 16.
Correct way to get the size of an array is - sizeof (x) / sizeof (x[0]). This will result in number of elements of array x.
This
ip = &(x[0]);
can also written as
ip = x;
because when you access an array, it is converted to a pointer to first element (there are few exceptions to this rule). Moreover,
From C Standards#6.5.2.1
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..
by this definition
&(x[0]) -> &(*(x + 0)) -> &(*(x)) -> x
You are initialising the array x with an empty initialiser:
int x[7] = {}
Empty initialiser is non-conforming in C, though some C compilers accept it. Instead, you should do:
int x[7] = {0}
Your desired output is 2, 4, 8, 16, 32, 64, 128 i.e. the first element of array should be 2 and every successive element in the array should be multiple of 2 of its previous element. Since, you want to calculate the value of every element of array using pointer pointing to that array element, one things you should know -
A pointer can point to one past the last element of array but dereferencing it will invoke undefined behaviour.
Putting these altogether, you can do:
#include <stdio.h>
int main (void) {
int x[7] = {0}, *ip;
ip = x;
*ip = 2;
for (size_t i = 0; i < sizeof (x) / sizeof (x[0]); ++i) {
printf ("value of x: %d\n", x[i]);
// make pointer point to next element in array
++ip;
// make sure that the element that ip pointer pointing to is valid to deference
if (ip < x + (sizeof (x)/sizeof (x[0]))) {
// calculate the element value using the previous element value
*ip = *(ip - 1) * 2;
}
}
return 0;
}
If you want to avoid the pointer comparison, you may do something like this:
#include <stdio.h>
int main (void) {
int x[7] = {0}, *ip;
ip = x;
for(size_t i = 0; i < sizeof (x) / sizeof (x[0]); ++i, ++ip) {
*ip = (i ? *(ip - 1) : 1) * 2;
printf("value of x: %d\n", x[i]);
}
return 0;
}

Following the perceived intent of your code, that is, to fill an array by using a pointer, I corrected it to the below.
#include <stdio.h>
int main()
{
int x[7] = {0};
int *p, counter;
for (p = &x[0], counter = 0; counter < 7;) {
*p++ = (1 << ++counter);
}
for (counter = 0; counter < 7; counter++)
printf("%d\n", x[counter]);
}
I initialise x and declare a pointer int *p. I also declare a variable counter to count to the number of elements in the array.
At the start of the loop I point p to the address of the first element of the array x and initialise counter to 0.
In each loop iteration I set the value at the address pointed by p to the result of a left-shift (or l-shift) operation and increment pointer p (that is, advance it by sizeof(int) bytes). The l-shift operation has the effect of raising 2 to the power of n, where n is the number of l-shift positions. For example:
(1 << 0) = 1
(1 << 1) = 2
(1 << 2) = 4
(1 << 3) = 8
I use the post-increment operator for p (that is, *p++) because I want to set the value before advancing it. But I use the pre-increment operator for counter (that is, ++counter) because I want the first l-shift to be by 1 position so that the result stored in the first element of the array is 2 -- refer to example above.

int x[7] = {}, *ip;
ip = &(x[0]);
In C, arrays are just pointers that you've told the proprocessor and compiler about so it can do the memory allocation on the stack for you. There's nothing special about the pointer itself with an array. In the above, ip and x are both int*, so you can just say ip = x;
*ip = 2;
x[0] now is 2
for(int i = 0; *ip < sizeof x; *ip *= 2){
Your middle condition *ip < sizeof x; in English is "until the int pointed to by ip is less than the number of bytes used by x (7 * sizeof(int); probably 7 * 4 or 28)" It's valid in that it will compile and execute, but I don't think it's what you want looking at the rest of your code. You never increment ip, so it's always changing x[0].
Assuming you just don't want ip to go past the end of x[], You could write this as i < sizeof(x)/sizeof(x[0]) which is "counter i is less than the total bytes used by x[] divided by the size in bytes of one element used by x (the number of elements in x[])" or if you want to use ip and not i for some reason ip <= &x[6] which is "ip is less than or equal to the address of the last element of x[] (because we know x is a fixed length of 7; [0...6]"
*ip *= 2
Your for incrementor is "the integer pointed to by ip is multiplied by 2". Normally you would increment your counter i here, but it's acceptable in C to do something else like you have here. However, since you never change ip, this is going to multiply the same x[0] by 2 over and over until x[0]'s value is more than sizeof(x). You probably want to increment ip or i here, so it steps through X[]. Normally the manipulation of your array would happen inside the for block and not in the for control statements.
printf("value of x: %d\n", x[i]);
This will always print the value of x[0], since i never changes.
Everything you've written is valid C code. Some of the things you're doing are unusual, but there are edge cases where you would want that in C, for example incrementing something other than your counter in the for loop control. However, you've got a extra code that isn't doing anything useful. I see what you want as output from your question details, but from your code I'm unsure how you want to accomplish that, so this is just a guess:
int x[7];
x[0] = 2;
printf("x[0] starts with: %d\n",x[0]);
for(int i = 1; i<sizeof(x)/sizeof(x[0]); i++) { //i start at 1 because we already set x[0]
x[i] = x[i-1]*2; //the current x[] = double the previous x[]
printf("value of x[%d]: %d\n",i,x[i]);
}
This version fills x with [2,4,8,16,32,64,128]. The int *ip isn't needed- there are times you'll want to control a loop with pointer math, but it's not needed here.

Related

Operator and Pointer precedence

Below is the problem I found on the internet.
int main()
{
int a[4] = { 10, 21, 32, 43};
int *p = a + 3;
++*--p;
++*p--;
p[2] += p[1];
for (int i = 0; i < 4; ++i)
printf("%d - %d\t", a[i]);
return 0;
}
//What will be the output?
answer : 10 21 34 77
I understood a lot of things, but the only thing I'm stuck on:
What is the difference between (++*--p) and (++*p--) ?
Shouldn't these two give the same result? Because (*p--) and (*--p) give the same result in the compiler. The compiler I use is Code::Blocks
Because (*p--) and (*--p) give the same result in the compiler.
No, they do not. *p-- decrements p but applies * to the value of p before the decrement. *--p applies * to the value of p after the decrement.
What is the difference between (++*--p) and (++*p--) ?
++*--p decrements p and increments the object it points to after the decrement.
++*p-- decrements p but increments the object it points to before the decrement.
What is the difference between (++*--p) and (++*p--) ?
The difference is that --p decrements p and resolves to the new value of p, whereas p-- decrements p and resolves to the old value of p.
++* works identically on both - performing indirection on p, incrementing the value p points to, and resolving to this new value.
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 10;
/* This prints 9, and `a` is now 9 */
printf("%d\n", --a);
/* This prints 10, and `b` is now 9 */
printf("%d\n", b--);
/* This prints 9 and 9 */
printf("%d %d\n", a, b);
}
Shouldn't these two give the same result? Because (*p--) and (*--p) give the same result in the compiler.
The order here matters, using (*--p) before (*p--) would resolve to the same element twice. Using (*p--) before (*--p) resolves to different elements.
#include <stdio.h>
int main(void)
{
int a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int *p = a + 4;
/* 4 then 4 */
printf("%d ", *--p);
printf("%d\n", *p--);
p = a + 4;
/* 5 then 3 */
printf("%d ", *p--);
printf("%d\n", *--p);
}

Pointer arithmetic in C not pointing to the correct variables if I don't print the address of the variables

So I'm doing pointer arithmetic homework and I need to decrement and increment pointers with this as its expected outcome. This is what I did
#include <stdio.h>
void main(void){
int d = 10;
int c = 8;
int b = 6;
int a = 4;
int *ptr; //these lines are given
printf("decrement \n");
for (ptr = &d; ptr >= &a; ptr--)
{
printf("%d \n",*ptr);
}
printf("increment \n");
for (ptr = &a; ptr <= &d; ptr++)
{
printf("%d \n",*ptr);
}
}
But the results skip 8 and 6:
decrement
10
4
increment
4
10
And so I decided to print the addresses at the beginning to help debug
printf("%p\n",(void*)&d);
printf("%p\n",(void*)&c);
printf("%p\n",(void*)&a);
printf("%p\n",(void*)&b);
But after running it, it just works
000000fc6a9ffb34
000000fc6a9ffb30
000000fc6a9ffb28
000000fc6a9ffb2c
decrement
10
8
6
4
increment
4
6
8
10
So I know that the logic works out, but it just doesn't work without printing first and I don't know why
I'm using Vscode and GCC
So I know that the logic works out, but it just doesn't work without printing first
Undefined behavior (UB), anything may happen.
int d = 10;
int a = 4;
int *ptr = &d;
ptr >= &a
ptr >= &a is undefined behavior (UB).
Order comparisons of pointers in C are UB when not part of the same array (or one after).
ptr-- is also UB as that attmepts to form the address before d. Pointer math only good within an array/object (or one after)
In your first example, you are not using variables b and c, just a and d - therefore (I suspect) the implementation is optimizing them away
In the second example, you are using variables all four variables a, b, c and d therefore they cannot be optimised away
your program have four different variables not an array of size four. So address of variables is unpredictable.
int d = 10;
int c = 8;
int b = 6;
int a = 4;
in Array memory is allocated contiguously, so use array if you want to do so.
#include<stdio.h>
int main(){
int arr[4] = {1, 2, 3, 4};
// increment
for(int i=0; i<4; i++)
printf("%d\n",*(arr + i));
// decrement
printf("-------------------------------\n");
for(int i=3; i>=0; i--)
printf("%d\n",*(arr + i));
return 0;
}

Values are not getting assigned to continuous addresses

Why on compiling the below piece of code is giving runtime error?
#include<stdio.h>
int main()
{
int i;
int *p;
int a = 10;
p= &a;
printf("address of a = %x\n",p);
*(p + 0) = 5;
*(p + 1) = 6;
*(p + 2) = 7;
*(p + 3) = 8;
for(i=0; i < 4; i++)
{
printf("address = %x value = %x\n",(p+i),*(p+i));
}
return 0;
}
In this code i am assigning values to the address of variable named a after that starting from address of a the values (6,7,8) respectively are getting assigned to the next address of a consecutively.
*(p + 1) = 6;
p is an int* - meaning that when you increment it by one, it doesn't jump one byte forwards - it jumps sizeof(int) bytes forward (probably 4 bytes). If you want to assign to the bytes separately, cast the pointer to a char*:
*((char*)p + 1) = 6;
When you write code like *(p + 1) = 6; - your program is very likely to crash. Per the standard this is undefined behavior, in practice what usually really happens behind the scenes is that since p == &a and a is on the stack, p + 1 points to 4 bytes in the stack above a - which likely contains some random value like a stack canary or a return address - and you are corrupting this value.
These expressions:
*(p + 1) = 6;
*(p + 2) = 7;
*(p + 3) = 8;
Create pointers that are past the memory bounds of a which are then subsequently dereferenced. Reading memory past the bounds of an object (or even attempting to create such a pointer if it is not just past the object) triggers undefined behavior.
In this particular case it caused your program to crash, but there is no guarantee that will happen.
You should allocate that memory before accessing it. Try using malloc().
Your code should look like this:
#include<stdio.h>
int main()
{
int i;
int a = 10;
char *p= (char *)&a;
printf("address of a = %p\n",p);
for (i = 0; i < sizeof(a); ++i) {
*(p + i) = i + 5;
}
for(i = 0; i < sizeof(a); ++i) {
printf("address = %p value = %d\n", p + i, *(p + i));
}
return 0;
}
One solution is to define p as a pointer to char. Another approach is, as suggested in other answers, just cast p into a pointer to char before any arithmetic. When using pointer arithmetic, the number of bytes you "jump" is as the size of the pointed type. So, p + 1 will jump 4 bytes, in case int is 4 bytes. This is why you should use a pointer to char if you want to move one byte at a time.
In addition, your loops should run N times, where N in the number of bytes. So, my suggestion is to use sizeof.
Last thing, please note that in order to print an int you should use %d, and use %p to print pointers (i.e addresses).

Why A[2][3] is valid lvalue for the declaration int *A [10];

int *A [10];
why A[2][3] is a valid lvalue. As I understand in A[2] we store a pointer to an integer(Single integer not an array). So how can [3] in A[2][3] access it?
Hopefully this code can demonstrate how int pointer arrays can be used.
The goal is to create a buffer big enough to hold 30 integers. Then assign an int pointer to every 3rd address division of the allocated buffer.
So if a[0] is set to address 0x562437eea260.
Then that means a[1] will be set to address 0x562437eea26c approximately (sizeof(int) * 3), 12, bytes away.
Then the values at the pointer's address can be set by calling a[i][j]; assuming i is the index that chooses the address from the int pointer array and j is either 1, 2, or 3 depending on what number you wish to access.
Expected Output:
a[0] = 0x562437eea260
a[0][0] = 2
a[0][1] = 3
a[0][2] = 5
a[1] = 0x562437eea26c
a[1][0] = 3
a[1][1] = 3
a[1][2] = 7
a[2] = 0x562437eea278
a[2][0] = 9
a[2][1] = 2
a[2][2] = 3
In my example, I set all integers to random values
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define UNUSED(x)((void)(x))
#define TOTAL_INT_POINTERS 10
#define INTS_PER_POINTER 3
int main(const int argc, const char** const argv, const char** const envp) {
UNUSED(argc); UNUSED(argv); UNUSED(envp);
// Seed random number generator
srand((unsigned int)time(0));
// Create and array that will hold 10 int pointers
int *a[TOTAL_INT_POINTERS] = {0};
// Allocate memory for integers
int *ptr = (int *)malloc((sizeof(int) * TOTAL_INT_POINTERS) * INTS_PER_POINTER);
if(ptr == NULL) {
fprintf(stderr, "Failed to allocate memory for integers!\n");
return (int)EXIT_FAILURE;
}
// Assign pointers and values to each allocated space
for(unsigned int i = 0; i < TOTAL_INT_POINTERS; i++) {
// Assign pointer array member
a[i] = ptr + (i * INTS_PER_POINTER);
// Print assigned address
printf("a[%d] = %p\n", i, a[i]);
// Give 3 integers their values and print out the result
for(unsigned int j = 0; j < INTS_PER_POINTER; j++) {
a[i][j] = rand() % 10;
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
putchar('\n');
}
// Free up used memory
free(ptr);
return (int)EXIT_SUCCESS;
}
As already pointed out in the comments, the compiler manages only the pointer and is not aware of the actual structure of your data. You can access array elements by index using square brackets or by using pointer arithmetics:
A[i][j] is equivalent to *(A[i] + j) and also equivalent to *(*(A+i) + j).
Note that you must ensure that the memory you are accessing is actually within the array bounds.
Further reading:
Multidimensional Pointer Arithmetic in C/C++
How to access two dimensional array using pointers in C programming?
The fact that x points to an int does not mean there are not more int next to that int, either before or after it or both.
If I have an array int a[10], then &a[5] points to element 5 of the array, and &[5] - 1 and &a[5] + 1 point to elements 4 and 6. If I pass &a[5] to a subroutine as its parameter int *x, and that subroutine knows other elements exist, it may use x[1] to refer to element 6 of the array and x[-1] to refer to element 4.
Given int *A[10], I can allocate as much memory as I want and assign its address to A[0]. Then A[0][0] points to space for the first int in that memory, A[0][1] points to space for the next int, and so on.

Printing pointer value with increment of the address in C

#include <stdio.h>
#include <stdlib.h>
int main()
{
int k,*ptr=NULL;
int arr[]={1,2,3,4,5,6,7,8,9,10};
ptr=arr;
printf("%d ",*ptr++);
printf("%d ",*(ptr++));
printf("%d ",(*ptr)++);
printf("%d ",*++ptr);
printf("%d ",++*ptr);
}
Why does the second printf print the number 2 ? It should print 3.
As everyone else said, the distinction is between pre-incrementing (where the increment occurs before the value is fetched) and post-incrementing (where the value is fetched and then the increment occurs). The value 2 should be printed, of course.
Maybe this assertion-laden code will help. The assert() macro stops the program if the condition specified is false when it is executed. The assertions do not fire.
The assertions show how the value of ptr changes, and also how the values in the array change.
#include <assert.h>
#include <stdio.h>
int main(void)
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int *ptr = arr;
assert(ptr == &arr[0]);
printf("%d\n",*ptr++); // print 1; ptr = &arr[1]
assert(ptr == &arr[1]);
printf("%d\n",*(ptr++)); // print 2; ptr = &arr[2]
assert(ptr == &arr[2]);
assert(*ptr == 3);
printf("%d\n",(*ptr)++); // print 3; ptr = &arr[2]; arr[2] = 4
assert(ptr == &arr[2]);
assert(*ptr == 4);
printf("%d\n",*++ptr); // print 4; ptr = &arr[3]
assert(ptr == &arr[3]);
assert(*ptr == 4);
printf("%d\n",++*ptr); // print 5; ptr = &arr[3]; arr[3] = 5
assert(ptr == &arr[3]);
assert(*ptr == 5);
printf("Offset: %d\n", (int)(ptr - arr));
for (int i = 0; i < 9; i++)
printf("a[%d] = %d\n", i, arr[i]);
return 0;
}
Output:
1
2
3
4
5
Offset: 3
a[0] = 1
a[1] = 2
a[2] = 4
a[3] = 5
a[4] = 5
a[5] = 6
a[6] = 7
a[7] = 8
a[8] = 9
post increment operator increments the variabl after accessing the value.
So, after getting *ptr, which is 2, ptr increases itself.
Not, because ptr++ return the value BEFORE the incrementation, so the value is 2.
*ptr++ first dereferences the pointer which gives 2, then increments the pointer
The expression *(ptr++) is a post increment expression so the value of of that expression is ptr and then it is incremented. So the result of the expression is that it still points to the 2
the * operator applies to the result of p++, which is the value of original p (prior to the increment). So it prints 2. I you want 3 to be printed you should do (++p) which returns the incremented value.
It should print 2, because the postfix operator ++ first returns the value and then increments it.
The fact that you added brackets around it (*(ptr++)) does not influence the increment.
The value will be incremented after the whole line.
Looking at disassembly might help you to see what happens at that line.
The *ptr++ returns the value at ptr and then increments it,so in the second printf() statement it only returns 2 and then increments it to 3.

Resources