Values are not getting assigned to continuous addresses - c

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).

Related

Pointers to an Array In C

So my book is explaining me pointers to an array using ts example
#include <stdio.h>
int main()
{
int s[4][2] = {
{1234,56},{1212,33},{1434,80},{1312,78}
};
int(*p)[2];
int i, j, * pint;
for (i = 0; i <= 3; i++)
{
p = &s[i];
pint = (int*)p;
printf("\n");
for (j = 0; j<= 1; j++)
{
printf("%d ", *(pint + j));
}
}
return 0;
}
The output is Given as
1234 56
1212 33
1434 80
1312 78
No issue I am getting the same output.
My question is what was the need of using another pointer pint ?
Why can't we directly use P?
So When I tried to do it using P directly it didn't work
printf("%d ", *(p + j));
I got garbage values in output, Why is this happening?
I also tried printing p and pint they are the same.
Although p and pint have the same value, p + 1 and pint + 1 do not. p + 1 is the same as (char *)p + sizeof *p, and pint + 1 is the same as (char *)pint + sizeof *pint. Since the size of the object pointed to is different, the arithmetic gives different results.
The pointer p is declared like
int(*p)[2];
So dereferencing the pointer expression with the pointer in this call of printf
printf("%d ", *(p + j));
you will get the j-th "row" of the type int[2] of the two dimensional array that in turn will be implicitly converted to a pointer of the type int * that will point to the first element of the j-th "row".
So instead of outputting elements of each row you will output first elements of each row that moreover results in undefined behavior when i will be greater than 2.

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;
}

Use of &ampersand and square bracket in printf

I came across the following code in an MCQ quiz,
#include <stdio.h>
int main()
{
int j =2, k =4;
printf(&j["Programming"], &k["Theory"]);
k = j ^ 3;
if (k == j)
printf(&k["Practical"], "Trytosolve");
else
printf(&j["Problem creation"]);
return 0;
}
where ampersand is used in the beginning itself and outside the quotes ("") of printf statement. I am only aware of the traditional use of printf statement and its format specifiers.
I tried to run this code, and it showed no error but this warning:
format not a string literal and no format arguments
and the following output
ogrammingoblem creation (this was one of the options in multiple choices)
I tried to search for such use, but could not find. Can someone explain this use of & and square brackets?
Say we have an array a and a variable i of integral type, then a[i] is equivalent to *(a + i), i.e. we can obtain the ith element of a by decaying a into a pointer to its first element, incrementing that pointer by i and dereferencing the result. This it true because arrays occupy contiguous addresses in memory.
Now, as it turns out, i[a] is also equivalent to a[i], this is more of a "trick" that nobody (to my knowledge) would ever use in production. It's sort of intuitively justifiable that this would be the case because a[i] == *(a + i) == *(i + a) == i[a].
So then, &j["Programming"] == &(*(j + "Programming")). And because dereferencing a pointer and then taking it's address is a noop, this is j + "Programming" == "Programming" + j == "ogramming", because strings are just arrays of characters.
Same for the other branch, which is executed because 2 ^ 3 == 1 != 2.
Maybe this example program will show you the math behind the scenes:
#include <stdio.h>
int main(void)
{
int j=2, k=4;
char *p1 = "Programming";
// Print the address of j
printf("&j = %p\n", &j);
printf("\n");
printf("Pointer arithmetic\n");
// Print the address of "Programming"
printf("p1 = %p\n", p1);
// Print the value of j
printf("j = %8d\n", j);
// Print the result of the pointer computation
printf("&j[\"%s\"] = %p\n", p1, &j[p1]);
// Print the result of the equivalent pointer computation
printf("p1 + j = %p\n", p1 + j);
printf("\n");
printf("Print strings\n");
// Print "Programming" after skipping the first two letters
printf("&j[\"%s\"] = %s\n", p1, &j[p1]);
// Print "Programming" after skipping the first two letters
printf("p1 + j = %s\n", p1 + j);
return 0;
}
Output
&j = 0x7fffb3325aa8
Pointer arithmetic
p1 = 0x4006e4
j = 2
&j["Programming"] = 0x4006e6
p1 + j = 0x4006e6
Print strings
&j["Programming"] = ogramming
p1 + j = ogramming

Returning array from function (C)

I'm extremely new to C programming, and am going through some tutorials. One thing that stumped me is with returning a pointer to an array. I've cut down the example from https://www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm to best illustrate my point.
#include <stdio.h>
int * getRandom( ) {
static int r[10];
int i;
for ( i = 0; i < 10; ++i) {
r[i] = i;
printf( "r[%d] = %d\n", i, r[i]);
}
return r;
}
int main () {
int *p;
int i;
p = getRandom();
for ( i = 0; i < 10; i++ ) {
printf( "*(p + %d) : %d\n", i, *(p + i));
}
return 0;
}
As one would expect, this prints
r[0] = 0
r[1] = 1
r[2] = 2
r[3] = 3
r[4] = 4
r[5] = 5
r[6] = 6
r[7] = 7
r[8] = 8
r[9] = 9
*(p + 0) : 0
*(p + 1) : 1
*(p + 2) : 2
*(p + 3) : 3
*(p + 4) : 4
*(p + 5) : 5
*(p + 6) : 6
*(p + 7) : 7
*(p + 8) : 8
*(p + 9) : 9
But when you change
static int r[10];
to
int r[10];
it instead prints
r[0] = 0
r[1] = 1
r[2] = 2
r[3] = 3
r[4] = 4
r[5] = 5
r[6] = 6
r[7] = 7
r[8] = 8
r[9] = 9
*(p + 0) : 0
*(p + 1) : 1980517315
*(p + 2) : -1164399724
*(p + 3) : 4199040
*(p + 4) : 4199040
*(p + 5) : 2285568
*(p + 6) : 19
*(p + 7) : 6356668
*(p + 8) : 8
*(p + 9) : 6356940
and I have no idea why. The only thing I can think of is that for some reason the compiler is reading the array cells as different data types, but I doubt that's right.
The static keyword is used to "remember" the value of r in the next call. If you remove it, then the memory allocated for r is flushed when the function returns, so you're just returning garbage.
When you have static int r[10];, the memory for storing the array is allocated at compile-time, and everything works as expected.
When you instead have int r[10], you are allocating your array on the run-time stack frame, which becomes invalid when the function call returns, and then gets overwritten by the next function call, so you see garbage.
The reason is that when you call getRandom() without a static array declaration, the array falls out-of-scope once the getRandom() function returns. This means that your pointer may no longer 'point' to r, because r is essentially discarded.
In order to return from getRandom() correctly, you would need to dynamically allocate your memory using malloc, for example:
int * getRandom( ) {
int *r = NULL;
r = malloc(sizeof(int) * 10); /* Create room for 10 integers*/
if (r == NULL) {
printf("Error: Could not allocate space\n");
return NULL;
}
int i;
for ( i = 0; i < 10; ++i) {
r[i] = i;
printf( "r[%d] = %d\n", i, r[i]);
}
return r; /* Returns a pointer to r*/
}
int main () {
int *p;
int i;
p = getRandom();
if (p == NULL) {
/*Error state*/
return 1;
}
for ( i = 0; i < 10; i++ ) {
printf( "*(p + %d) : %d\n", i, *(p + i));
}
free(p); /* Free the memory we allocated*/
return 0;
}
Note how we must free the memory we allocated (otherwise we would have memory leaks). Also note that we must handle the NULL case, where we could not allocate the memory necessary.
Excepting by a few cases, an array in a expression always decays to the address of its first element.
This pointer is the value returned by the function.
The array itself, as an object living in memory, in general dies after the function execution finished.
So, the memory address pointed by the pointer that the function returned is not guaranteed to preserve the array, and it could have garbage instead.
The static declaration preserves the array object, but still your function have returned a pointer to the head of the array and not the array itself.
It is bad practice to return a pointer to an inner static object of a function,
because you are allowing to any user of your function to change the values of the array from outside of the function in umpredictable ways.
If you want to return a complete array, as a value, perhaps you should define a struct type containing an array field, in this way:
typedef struct { int sub[10]; } wrappedarray_t;
wrappedarray_t getRandom(void) {
wrappedarray_t r;
// sentences....
return r;
}
wrappedarray_t p = getRandom();
printf("0th element: %d\n", p.sub[0]);
because you're using a locally allocated piece of data; once the program goes out of scope, then all the data you saved to it is thrown out and it'll return garbage values.
In this situation, you can do two things:
either malloc() a pointer-array OR use the static array and return one of them.
ANOTHER option you can do is to put an array buffer in the function parameters so the data is copied to that buffer.

Why can uninitialized pointer to int array be assigned variable's value?

I have read answers to questions like why a pointer can be assigned value? however I'm still a bit confused about changing the values of pointers. Some of the comments don't seem to be completely accurate, or maybe it's implementation specific. (example: a[1] is exactly the same as writing *(a + 1). Obviously you can write *a = 3 since a is int*, so you can also write *(a + 1) = 3, so you can also write a[1] = 3).
Writing *a = 3 produces a warning: initialization makes pointer from integer without a cast. As well as a segfault.
My question is as follows.
int main(void)
{
int b = 5, c = 10;
int *a = b;
*a = c; /* Will not work. (Should technically change the value of b to 10, leaving the pointer still pointing to b.) */
printf("%d\n", *a);
return 0;
}
The above example will not work, and will produce a segfault, but the following works for some reason I am not aware of.
int main(void)
{
int a[10], i;
for (i = 0; i < 10; ++i) {
*(a + i) = i; /* Supposedly the same logic as '*a = c;', but works*/
}
for (i = 0; i < 10; ++i) {
printf("%d\n", *(a + i));
}
return 0;
}
Thanks for your time and efforts.
**EDIT: Thank you for the answers, since it is *a = &b (I knew this (typo), but now the second example with the loop is unclear), the array indices are treated as variables, not as addresses I presume?
This:
int b = 5, c = 10;
int *a = b;
Doesn't work. You think the second line means this:
int *a;
*a = b;
But it doesn't. It means this:
int *a;
a = b;
The above error means that when you do this:
*a = c;
Your program crashes (or maybe not, undefined behavior!), because a is an invalid pointer (it points to address 5, which is wrong in many ways).

Resources