This code causes a segmentation fault when running. It's due to the odd pointer incrementation, but I don't understand why this is a problem, as it seems to make sense.
I think it should: increment the pointer, then dereference the unincremented pointer, then increment the value 10 to 11. So out = 11, and the first value in the array is now 11. So this loop should print out 11, 21, 31, 1, then go on infinitely printing out values outside the array. This is clearly bad practice but we just want to see why this double pointer incrementation isn't valid.
My code:
int main() {
int myarray[4] = {10,20,30,0};
int *p = myarray;
int out = 0;
while (out = ++(*p++)) {
printf("%d ", out);
}
}
The while loop never terminates:
First iteration:
*p = 10, out = 11
Next iteration:
*p = 20, out = 21
Next iteration:
*p = 30, out = 31
Next iteration:
*p = 0, out = 1
Next iteration:
You are accessing unauthorized memory, which leads to undefined behavior.
Update
After the last item from the array is accessed, the part of the stack frame that contains code gets trampled over by the increment operator. Hence, the code cannot be expected to behave in a logical manner.
Here:
while (out = ++(*p++))
The preincrement (the first "++") returns the incremented value. So when you reach the end of the array, it returns 1, which evaluates to true, and the loop keeps going.
When p exceeds the range of myarray, deference causes undefined behavior.
Related
int main() {
int j = 0;
int i = 0;
for (j = 0; j < 5; j++) {
printf("Iteration %d : %d ", j + 1, i);
int i;
printf("%d", i);
i = 5;
printf("\n");
}
}
The above code generates the following output:
Iteration 1 : 0 0
Iteration 2 : 0 5
Iteration 3 : 0 5
Iteration 4 : 0 5
Iteration 5 : 0 5
I'm not able to understand why the second printf value in iterations 2,3,4,5
is 5.
My understanding of why the first value is 0 in each iteration is that the scope of i in the for loop is local and it is destroyed as soon as we go into a new iteration as i was declared in the for loop.
But I'm not able to figure out why this value becomes 5 at the second printf.
The behaviour of your program is undefined.
The inner scope i is not initialised at the point it's read.
(What might be happening is that the reintroduced i on subsequent iterations occupies the same memory as the previous incarnation of the inner i, and the uninitialised memory on the first iteration corresponds to 0. But don't rely on that. On other occasions, the compiler might eat your cat.)
The second printf in your program is printing garbage value from uninitialized local variable i. In general case the behavior is undefined.
By accident, storage location that represents your i (memory cell or CPU register) is the same on each iteration of the cycle. By another accident, the body of your cycle is executed as a single compound statement for each iteration (as opposed to unrolling the cycle and executing all iterations at the same time in interleaved fashion). By yet another accident, the storage location of i keeps its old value from the previous iteration. So, the garbage that you are printing matches the last stored value from that location on the previous iteration of the cycle.
That's why you see 5 in local i on each iteration besides the first. On the first iteration that garbage value happened to be 0.
I think this is what is happening:
Breakpoint 1, main () at abc.c:4
4 int j = 0;
(gdb) s
5 int i = 0;
(gdb)
6 for(j=0;j<5;j++){
(gdb) p &i
$23 = (int *) 0x7fff5fbffc04 //(1) (addr = 0x7fff5fbffc04) i = 0
(gdb) p i
$24 = 0 // (2) i == 0
(gdb) s
7 printf("Iteration %d : %d ",j+1,i);
(gdb) p &i
$25 = (int *) 0x7fff5fbffc00 //(3) here compiler finds there is contention in variable 'i' and assigns the inner one which is in present scope. Now, when subroutines are called, the stack frame is populated with (arguments, return address and local variables) and this is when the inner 'i' was also got allocated in this inner loop block but not initialized yet and this is the reason i get garbage value in the first integration output.
(gdb) p i
$26 = 1606417440 // (4) Here i == 1606417440 (Garbage)
(gdb) s
9 printf("%d",i);
(gdb) s
10 i = 5;
(gdb) p &i
$27 = (int *) 0x7fff5fbffc00
(gdb) p i
$28 = 1606417440
(gdb) s
11 printf("\n");
(gdb) p &i
$29 = (int *) 0x7fff5fbffc00
(gdb) p i //(5) after executing previous statement, now i == 5
$30 = 5
(gdb)
C compilers have some latitude in how they implement things and it would not be at all unusual for the local "i" to not actually be recreated each pass of the loop. It is likely actually only being created once, and re-used on each pass. In this case, your first print is outside the scope of the local variable so uses the i from outside the loop. The second print uses the local i as it is in scope, and after the first iteration has been set to 5. On the first iteration, the correct value is undefined, not 0, but the behavior of undefined is implementation specific, in your implementation it appears to automatically be initialized to 0.
If you declare a local variable and don't give it a value before using it, if you get is undefined behavior.
C standard say,
Variables with automatic storage duration are initialized each
time their declaration-statement is executed. Variables with automatic
storage duration declared in the block are destroyed on exit from the
block.
So, I'm just practicing something in C language (I'm a beginner), but I'm now stuck on this program:
#include <stdio.h>
#include <string.h>
int main(){
int numbers[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
int i;
int *point;
point = numbers;
while(i){
printf("Write number in ranging 1 - 40: \n");
scanf("%d", &numbers);
if (numbers, point){
printf("Your number is prime number.\n");
}
else if ((numbers <= 0) || (numbers >= 41)){
printf("Only numbers: 1 - 40.\n");
}
else{
printf("Try again.\n");
}
i;
}
return 0;
}
When I want to compile it, I just get this error message:
test.c: In function ‘main’:
test.c:19:38: warning: comparison between pointer and integer [enabled by default]
I looked around Stack Overflow, but I found nothing of similar topic and didn't help me.
Even if you're a beginner, you should still take the effort to tell us which lines are giving you errors, since it's not easy to tell exactly what line is number 19.
I think this line is giving you trouble.
if (numbers, point){ // bad
You probably meant to call some function that takes numbers and point as an argument. As it is right now, this if statement will always evaluate to true because you are using the comma operator, which just uses the value of the thing on its right, which happens to be a non-null pointer (point). How about something like:
if is_a_prime(numbers, point)
Moving on, the line that actually is causing the error is most likely this line:
else if ((numbers <= 0) || (numbers >= 41)){ // bad
Since numbers is an array, it doesn't make much sense to write numbers <= 0. Perhaps you meant to write numbers[0] <= 0, or *point <= 0, or maybe you wanted to use a for loop to iterate over each number in the array to make sure it is positive.
Also, (thanks to isedev for seeing this), you never set i to any value before accessing it, so your program will have undefined behavior. Try writing something like i = 1; near the top.
First of all, this program will most likely not run. Specifically because you are saying while (i) when i is uninitialized (i.e garbage). It might be zero or any other value its initial address happens to point to.
Secondly, what do you mean by if (numbers, point) ? That doesn't mean anything.
Also, point is numbers, so there's no reason to compare them.
Thirdly, if you want to check for a prime number use the modulo operator. Like this.
Lastly, a pointer is not an integer or an array. When you say point = numbers that just stores the address of numbers in memory into point, and using pointer arithmetic (and because pointer[3] and array[3] mean the same thing ~ pointer + (3 * sizeof(datatype))), you might think that a pointer is an array, but it's not. Here's an example:
int h, *p;
h = 5;
*p = &h;
printf("*p: %d\n", *p);
h = 8;
printf("*p: %d\n", *p);
Here, *p is the value of h, and for a really simple reason.
p stores the address of h in memory, and when you say h = 5 the computer changes the value found at the address of h in memory. And because p happens to store the address itself in it, it can simply get the value found there. In short, p has no relation to h, dot.
There are a couple of problems in this code:
Your i value variable is uninitialized
If the garbage value of i is non zero its an infinite loop
In the if condition you need to do a logical operation
You are using scanf() not with pointer you use are using pointer to pointer
I am unable to understand the following code in С, using pointers
#include <stdio.h>
#include <stdlib.h>
int bags[5]={20,5,20,3,20};
int *next();
int main()
{
int pos=5;
*next()=pos;
printf("%d,%d,%d",pos,*next(),bags[0]);
}
int *next()
{
int i;
for(i=0;i<5;i++)
if(bags[i]==20)
return(bags+i);
printf("Error!");
}
Can anyone explain why the ans is 20,5,20.
The output of the program will is,
5,20,5
because
if(bags[i]==20)
return(bags+i);
returns pointer to bags[0] since bags[0]==20 and return is a pointer to it and
*next()=pos;
writes pos value to the address pointed by next() returned address, i.e. bags[0]=pos=5
The function next returns a pointer to the first array element equal to 20.
So, *next()=pos; will modify the first element of the array from 20 to 5.
Then it is simple to understand why the output is 5,20,5: since pos is five, *next() returns 20 and bags[0] is 5 as explained above.
The output is 5,20,5.
Note: int *next(); ==> next() is a function that returns int*.
[1] The call to next() from the line *next() = pos;. C evaluates the function from left so next() gets called first. Because of if (bags[i] == 20), the function next() returns bags+i which is simply bags since i is 0 at the moment. So next() returned the address of bags which means *next() is nothing but the pointer to bags[0]. So bags[0] becomes 5.
[2] When the execution comes to this line: printf("%d,%d,%d",pos,*next(),bags[0]);, it prints value of pos i.e 5, value of *next() which is 20 as next() returned the address of bags[0].
[3] *next() prints 20 because, this time next will return the address of bags[2] since bags[0] got assigned with the value of pos in the line before the printf().
[4] And finally, bags[0] is 5. See the explanation in [1].
new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.
I am trying to understand how the pointers are moving.
Following is the program and I am aware that
if
int cs={1,2,3};
then cs points to cs[0]
what I am not clear is what is *cs pointing to.
#include<stdio.h>
int main()
{
int array[] = { 1, 2, 3, 4, 5 };
int *arrptr1 = array;
int *arrptr = array;
int i;
for (i = 0; i < sizeof(array) / sizeof(int); i++) {
printf("%d, %d, %d\n", array[i], *arrptr1++, *arrptr + i);
}
}
the output of above program is
1, 1, 1
2, 2, 2
3, 3, 3
4, 4, 4
5, 5, 5
then my understanding *arrptr should increase the value stored at
*arrptr
should get incremented by 1.
Where as what I observe is the pointer is moving to next location.So just want to know what is wrong in my understanding?
UPDATE
As per the replies below I understand that
print("%d", *arrptr1++);
in such a statement evaluation of operators is from right to left.
Hence in *arrptr1++ the ++ will get evaluated first and then arrptr and then *
So to confirm the same I wrote another program
#include<stdio.h>
int main()
{
int array[] = { 10, 20, 30, 40, 50 };
int *q1 = array;
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1++);
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1);
}
The output of above program is different than the expected operator precedence by above logic.
The output I got is
q1 = 0x7ffffcff02e0
*q1++ = 10
q1 = 0x7ffffcff02e4
*q1++ = 20
So I was expecting in the 2nd line of output instead of *q1++ = 10 following *q1++ = 20
so did the operator precedence not happened right to left?
*arrptr1++ is parsed as *(arrptr1++), not (*arrptr1)++.
Whenever you use dereference operator * and pre-increment(pre-decrement) or post-increment(post-decrement) operator on a variable simultaneously ,the order of operation is from right to left (if parenthesis are not used).
What you want to do is
(*arrptr)++
because of higher precedence of (), it will force the compiler to first access the element pointed to by arrptr and then increment its value.
When you do this *arrptr++ , as I've said it first operates rightmost operator (i.e. ++)
and then the dereference operator.
If you will write
EDITED (only the comment): *++arrptr // increment the pointer then access
it will first advance the pointer and then access the value
stored in the address now pointed to by arrptr.
One more thing,The comma used for separation of function argument is not the comma operator so the order of evaluation of the arguments is undefined. (already been told)
What happens is that *arrptr1++ is interpreted as *(arrptr1++), which means that the pointer to the array is increased by one each time in the loop, and hence it will point to the same element as array[i]. *arrptr + i on the other hand is interpreted as "the value of the array element pointed to by arrptr plus the integer i". In this loop it means it will display the same thing as array[i], but it is not pointing at the same element (arrptr is always pointing to the first element in your array). If you change the values in the array to something more random, it should be obvious when you run the program again.
cs = &cs[0] ( cs is equal to the address of cs sub 0) ; *cs = cs[0] (cs pointer is equal to cs sub 0) ; You should remember that *'s hide the [].
// here is a print function with a pointer
int foo[5] = { 2, 9, 1, 3, 6};
int *walker, count;
walker = foo;
for (count = 0; count < 5; walker++, count++)
printf("Array[%d]: %d\n", count, *walker);
Recap: walker is equal to &foo[0], so when you increment walker (eg. walker++) you're moving the pointer to the next address which is foo[1]. And when we are printing the value we can't say ..., walker); since walker( &foo[whatever] ) is pointing to an address, we need to dereference the pointer to get the value. Again, the most important thing to remember
array = &array[0] AND *array = array[0]