How C static pointer guards repeating work? - c

I'm a C new learner,
when learning llvm, I met the following code
#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>
// This callback is inserted by the compiler as a module constructor
// into every DSO. 'start' and 'stop' correspond to the
// beginning and end of the section with the guards for the entire
// binary (executable or DSO). The callback will be called at least
// once per DSO and may be called multiple times with the same parameters.
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
static uint64_t N; // Counter for the guards.
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
printf("%p \n", x);
}
static uint64_t N; matters
Counter for the guards.
without it, the following for loop repeats.
I know what it can do.
How does it work ?
Here is what the above code prints:
INIT: 0x104351508 0x104351544
0x104351508
0x10435150c
0x104351510
0x104351514
0x104351518
0x10435151c
0x104351520
0x104351524
0x104351528
0x10435152c
0x104351530
0x104351534
0x104351538
0x10435153c
0x104351540
after uint32_t *x = start;
why *x = ++N; does not change x's position?

why *x = ++N; does not change x's position?
It seems you are confused about "the value of a pointer" and "the value a pointer points to" (aka the value of the pointed to object).
The value of the pointer x is initialized by
uint32_t *x = start;
\---------/ \------/
Defines Initializes the value of the pointer to equal the value of start
the
pointer x
Then the value of x is changed by this code:
x++
This part
*x = ++N;
will not change the value of x. Instead it change the value of the pointed to object.
If you change
printf("%p \n", x); --> printf("%p %u\n", x, *x);
you'll see output like
INIT: 0x104351508 0x104351544
0x104351508 1
0x10435150c 2
0x104351510 3
0x104351514 4
0x104351518 5
0x10435151c 6
0x104351520 7
0x104351524 8
0x104351528 9
0x10435152c 10
0x104351530 11
0x104351534 12
0x104351538 13
0x10435153c 14
0x104351540 15
where the first column is the value of the pointer x and the second column is the value of the pointed to object.
In the question you write:
static uint64_t N; matters
Counter for the guards.
without it, the following for loop repeats.
It's a bit unclear exactly what you are asking here but using the keyword static means that the object N preserve its value between calls. In other words, if you call the function again after the example above then N will have the value 15 to start with. So if you provide a new area (i.e. new start and stop values), you could see something like:
INIT: 0x104351600 0x10435160c
0x104351600 16
0x104351604 17
0x104351608 18

Related

Does adding values to a variable in printf() change the overall value of x?

int main() {
x=5;
printf("%d",x+3);
}
x could be either 5 or 8 after this example (I know that the output on the screen would be 8.)
The value at the address of x remains unchanged in this example. Inside the printf, we first get the value at the address of x and then add it to 3 and output it to the screen.
This is why we use statements like x=x+3 to change the value.
This kind of thing doesn't exist. What's best to do is to perform the operation outside of the printf() function:
#include <stdio.h>
int main() {
int x = 5;
x += 3; // x = x + 3
printf("%d\n", x);
}
According to Tomo Ceferin, x won't change because of the language's logic.
This works in C99. Not sure if any other version does.
#include <stdio.h>
int main() {
int x = 5;
printf("%d\n", x += 3);
}
Your program does not compile because there is no definition for x.
You should also include <stdio.h> to declare printf properly.
The statement printf("%d", x + 3); does produce 8 on standard output, but it does not modify the variable x, assuming x is defined as int x; somewhere.
You could modify x inside the call to printf: this has always been supported by the C language, although it is considered confusing.
#include <stdio.h>
int main() {
int x = 5;
printf("%d\n", x += 3); // prints 8 with a side effect
// x now has a value of 8
printf("%d\n", x); // prints 8 again
return 0;
}
The value of x remains the same, because you do not change it at all. Also, you should take into account to declare what type of data is your variable.
For example:
int main(){
int x = 5; //this is the variable x, declared as an integer. Its value is 5.
printf("%d", x + 3) //here you print an integer variable which has the value of (x+3),
//(5 + 3 = 8), to be more precise. (this instruction has nothing to
//do with the value of x, because you're not changing x in any way.)
}
So you will get on the screen the value of 8.
Hope it helped.

While-loop not breaking when extra 'int' keyword added?

I was doing some exercises on codewars, and had to make a digital_root function (recursively add all digits of a number together, up untill there's only one digit left).
I was fairly confident that I did it right, but for some reason my while-loop never broke, even though my prints showed that len was 1.
#include <stdio.h>
#include <string.h>
int digital_root(int n) {
char number[10];
sprintf(number, "%d", n);
int len = strlen(number);
printf("Outer print: %s %d %d\n", number, n, len);
int sum = 0;
while(len > 1)
{
sum = 0;
for(int i = 0; i<len; i++)
{
sum += number[i] - '0';
}
sprintf(number, "%d", sum);
int len = strlen(getal); //!!!
printf("Inner print: %s %d %d\n", number, sum, len);
}
return sum;
}
It took me a long time to figure out what was wrong. I noticed that I copy pasted the 'int' keyword when I recalculated the len in the while loop (line marked with !!!). When I removed that (because it was not needed to redefine it as an int, it already was), everything suddenly worked like it was supposed to.
This kinda confused me. Why would this matter? I understand that redefining it is bad practice, but I don't get how this would result in the while-loop not breaking?
The used compiler is Clan3.6/C11.
(Ps. When I tried the same code in TIO, it worked in both cases...)
You're not redefining an existing variable, you're defining a new variable.
Consider this example:
#include <stdio.h>
int main(void) {
int x = 42;
printf("Outside, start. x (%p) = %d\n", (void *)&x, x);
{
printf("Inner block, start. x (%p) = %d\n", (void *)&x, x);
int x = 123;
printf("Inner block, end. x (%p) = %d\n", (void *)&x, x);
}
printf("Outside, end. x (%p) = %d\n", (void *)&x, x);
return 0;
}
Sample output:
Outside, start. x (0x7ffd6e6b8abc) = 42
Inner block, start. x (0x7ffd6e6b8abc) = 42
Inner block, end. x (0x7ffd6e6b8ab8) = 123
Outside, end. x (0x7ffd6e6b8abc) = 42
[Live demo]
This program outputs the memory address and value of x. Most uses of x refer to the outer variable declared at the beginning of main. But within the inner block, after int x = 123;, all occurrences of x refer to a second, separate variable that happens to also be called x (but is otherwise independent).
When execution leaves the inner block, the outer x variable becomes visible again.
This is also referred to as shadowing.
In your code, the outer len is never modified, so while(len > 1) is always true.
By the way, shadowing is a very common concept in most languages that support block scoping:
Perl
JavaScript
Haskell
Common Lisp
Your second int len creates a second, parallel, variable that goes away at the end of the {} block. The original len then returns to life, completely unchanged. Without the second int the original variable is changed. With it the original len is effectively an unchanged constant and infinite loop.

C - Does a variable declared in loop get the memory at same place each time the loop executes?

Please read the code below.
#include <stdio.h>
int main(void)
{
char* a[4];
int i=0;
while(i<3)
{
char b[50];
scanf(" %s",b);//Assume user enters one two three
a[i++]=b;
}
i=0;
while(i<3)
printf(" %s ",a[i++]);//Why does it always print three three three
return 0;
}
Clarify the following:
Is it that b gets allocated same 50 bytes in memory each time so that all the elements of array a point to same 50 bytes and thus we get only three printed three times(i.e. what's entered last)
Since after the completion of while, array b can be removed very well but no it remains there every single time printing only three's. Why?
Is it not at all a coincidence that this code prints only three's when it could print one two three, one three three as well. What's wrong?
I know the question is very wrongly put. Forgive me for that. I am new here.
QUESTION #1:
The variable b is a variable that is strictly local to the
while loop.
Therefore, do not reference via a pointer any memory formerly used by b outside (after) the while loop.
Storage for b will be reallocated 3 times.
At the end of the while loop, b will go out of scope.
QUESTION #2:
After the while loop, a is not a valid pointer anymore
because a was assigned to point to b,
and b has gone out of scope after the while loop.
NEVERTHELESS, the memory allocated to b may still
not have been modified. You cannot predict what the value of dereferencing a will be after the while loop - since a is only assigned based on b.
QUESTION #3:
(Please see #2) The code that is dereferencing a after the while loop is using a stale pointer - I would not rely on the output.
The code in the question exhibits undefined behaviour because the second loop attempts to access the data that was only valid in the first loop. Therefore, there is very little that can usefully be said.
The question title is "does a variable declared in a loop get the same address each time the loop executes". Here's a proof by counter-example that the address of the variables in a loop need not always be the same, even in a single invocation of a non-recursive function.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand(time(0));
for (int i = 0; i < 3; i++)
{
int n = rand() % 30 + 5;
char a[n];
for (int j = 0; j < n - 1; j++)
a[j] = rand() % 26 + 'a';
a[n-1] = '\0';
printf("a: %p %2d [%s]\n", (void *)a, n, a);
char b[50+n];
scanf("%s", b);
printf("b: %p %2d [%s]\n", (void *)b, n+50, b);
}
return 0;
}
On a Mac running macOS Sierra 10.12.4 (using GCC 7.1.0), one run of the program (lv83) produced:
$ ./lv83 <<< 'androgynous hermaphrodite pink-floyds-greatest-hits-dark-side-of-the-moon'
a: 0x7fff507e53b0 23 [sngrhgjganmgxvwahshvzt]
b: 0x7fff507e5360 73 [androgynous]
a: 0x7fff507e53c0 9 [wblbvifc]
b: 0x7fff507e5380 59 [hermaphrodite]
a: 0x7fff507e53b0 26 [pqsbfnnuxuldaactiwvjzvifb]
b: 0x7fff507e5360 76 [pink-floyds-greatest-hits-dark-side-of-the-moon]
$
The address at which the two arrays are allocated varies depending on how big they are. By using different formulae for the sizes of the two arrays, the base addresses could be tweaked. It looks as though the compiler rounds the base address of the arrays to a multiple of 16.

Why is the input of the following program is as described: Pointers, extern values

int x=0;
int*a=&x;
void foo(int * a) {
static x=0;
x++;
printf("x's value %d ", x);
*a+=x;
a=&x;
*a=x+10;
}
int main(void) {
foo(a);
printf("a's value %d\n ", *a);
foo(a);
printf("a's value %d ", *a);
return 1;
}
I'm trying to analyze the above. First iteration of foo, when the function reaches to a=&x, the a after the function stops to get affected by what happens, since at the end of the function the pointer would go back to the original value he pointed to, now 1. the static x is now 1 as well. Second iteration: How's x got the value 12?! the static x became 2, and so I expected 3 to be the value of a.
The output is:
x's value 1 a's value 1
x's value 12 a's value 13
a=&x;
*a=x+10;
The above code adds 10 to x, because you set a to be a pointer to x, and then set the value pointed to by a to x+10.
The line a=&x makes a point to the static function-local variable x (since it's the innermost in scope). Thus *a=x+10 in the next line is equivalent to x=x+10, and x is 11 as we exit the function. At the next call, we increment x by 1, and it becomes 12.

Does making the iterator a pointer speed up a C loop?

I ran the following:
#include <stdio.h>
typedef unsigned short boolean;
#define false 0
#define true (!false)
int main()
{
int STATUS = 0;
int i = 0;
boolean ret = true;
for(i = 0; i < 99999; i++)
{
ret = ret && printf("Hello, World.");
}
if(!ret)
{
STATUS = -1;
}
return STATUS;
}
It completes in just under a second. Typically 0.9 - 0.92.
Then I changed int i = 0; to int *i = 0; and now I am getting execution times under 0.2 seconds. Why the speed change?
Your runtime is dominated by the time required to print to the console. i++ on an int* will increment the pointer by the size of a pointer. That will be either 4 or 8 depending on your computer and compiler settings. Based on the numbers you report, presumably it would be 4. So printf is executed only a quarter as many times.
Typically, printing to a console will be several orders of magnitude larger than any gain with micro optimization you could do to such a loop.
Are you really sure your second version prints hello world 99999 times as well ?
When you're doing for(int *i = 0; i++ ; i < 99999 ) , you're cheking if the pointer value(an address) is less than 99999, which doesn't normally make a lot of sense. Incrementing a pointer means you step it up to point at the next element, and since you have an int*, you'll increment the pointer by sizeof(int) bytes.
You're just iterating 99999/sizeof(int) times.
Your comment on nos's answer confirmed my suspicion: it's pointer arithmetic. When you increment an int pointer using ++, it doesn't just add one to the number, but it actually jumps up by the size of an integer, which is usually 4 (bytes). So i++ is actually adding 4 to the numeric value of i.
Similarly, if you use += on a pointer, like i += 5, it won't just add 5 (or whatever) to the numeric value of i, it'll advance i by the size of that many integers, so 5*4 = 20 bytes in that case.
The reasoning behind this is that if you have a chunk of memory that you're treating as an array,
int array[100]; // for example
you can iterate over the elements in the array by incrementing a pointer.
int* i = array;
int* end = array + 100;
for (i = array; i < end; i++) { /* do whatever */ }
and you won't have to rewrite the loop if you use a data type of a different size.
The reason is because the increment operates differently on pointers.
On ints, i++ increments i by 1.
For pointers, i++ increments by the size of the pointed-to object, which will be 4 or 8 depending on your architecture.
So your loop runs for only 1/4 or 1/8 of the iteration count when i is a pointer vs when i is an int.
The correct way to do this test with a pointer would be something like:
int i;
int *i_ptr = &i;
for (*i_ptr = 0; *i_ptr < 99999; *i_ptr++) {
...

Resources