Very classic C language interesting topic

  • 2020-04-01 21:35:56
  • OfStack

(link: http://stevenkobes.com/ctest.html)

There's an interesting set of C language quizzes on this site, and if you're hiring C developers or learning C, it's worth doing.

If not, do not read the following content for the moment, it is best to complete it yourself.

< img border = 0 title = image border = 0 Alt = image SRC = "/ / files.jb51.net/file_images/article/201304/201304111014595.png" width = 372 height = 488 >

OK, assuming you don't get the answer exactly right, then you can continue reading, otherwise, the rest of the content is a piece of cake for you, not worth watching.

The first question:

# include < Setjmp. H>
The static jmp_buf buf.
Int main (void)
{
Volatile int b = 3;
If (setjmp (buf)! = 0)
{
Printf (" % d \ n ", b);
The exit (0);
}
B = 5;
Longjmp (buf, 1);
}

The output is A) 3 B) 5 C) 0 D) neither

And that's choice B, which is output 5.

Key point is to understand setjmp and longjmp () (link: http://en.wikipedia.org/wiki/Setjmp.h) the first run to setjmp, will set the jmp_buf, then returns 0. When calling longjmp, the non-0 value in longjmp will be returned as the return value of setjmp (if the value parameter of longjmp is 0, the return value of setjmp will be 1 after setjmp recovery, that is, when the recovery of setjmp memory point, setjmp will not return 0).

The setjmp-longjmp combination is similar to the save/read function in the game and is often used for exception recovery operations like C++.

The second question:

Struct node
{
Int a; Int b; Int c;
};
Struct node s = {3, 5, 6};
Struct node *pt = &s;
Printf (" % d \ n ", * (int *) pt);
So it returns 3, which is pretty simple, pt is the pointer to s, and then convert pt to an int, dereference, and get an int, that's the first number in the structure.

Let's change the title a little bit, with the following code


struct node 
{ 
char a; char b; short c; int d; 
}; 
struct node s = { 3, 5, 6, 99 }; 
struct node *pt = &s; 
printf("%Xn", *(int*)pt);


It is important to note that the general 32-bit C compiler considers char to be 8bit, short to be 16bit, and int to be 32bit, so node should be exactly aligned in memory, that is, there is no space between the members of ABC. The end result should be 60503, if not, you are welcome to tell me your specific compilation environment and hardware configuration.

The third question:


int foo(int x, int n){ 
int val = 1; 
if (n > 0) 
{ 
if (n % 2 == 1) val *= x; 
val *= foo(x * x, n / 2); 
} 
return val; 
}


The easiest way to solve this problem is to make a deduction on paper and run through it step by step to get the answer. There are no complicated C concepts involved.

The fourth question:


int a[5] = { 1, 2, 3, 4, 5 }; 
int *ptr = (int*)(&a + 1); 
printf("%d %dn", *(a + 1), *(ptr  �  1));


This problem is actually a pointer to an array. &a is an implicit pointer to an int [5] array, which is different from int* PTR. If you really want to define this pointer, it should be int (*ptoa)[5]. So ptoa each plus one operation is equivalent to memory step across the int a [5] (that is, five int length), that is to say, & a + 1 is to point to a [5] this position, in fact the memory inside this position is illegal, but behind the casts of PTR led to the PTR - 1 memory step change to an int length, so the actual PTR - 1 point to a [4]. There's nothing to say about a plus 1, which is 2.

Question 5:


void foo(int[][3]); 
int main(void) 
{ 
int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; 
foo(a); 
printf("%dn", a[2][1]); 
return 0; 
} 
void foo(int b[][3]) 
{ 
++b; 
b[1][1] = 9; 
}


In fact, the step size of ++b is actually 3 int, that is, after ++b operation, b points to the beginning of the array {4,5,6}, and b[1] is {7,8,9}, b[1][1] is actually the value of 8, namely a[2][1] in the main function.

Question 6:


int a, b, c, d; 
a = 3; 
b = 5; 
c = a, b; 
d = (a, b); 
printf("c=%d ", c); 
printf("d=%dn", d);


There are actually two C language points about this, one is that the equal sign operator takes precedence over the comma operator, and the other is that the comma operator corresponds to the operation of the first and second half of the expression of the comma, and then returns the value of the second half of the expression. So c is equal to a (evaluate the equal sign first), and d is equal to b (the comma expression returns b).

Question 7:


int a[][3] = {1, 2, 3, 4, 5, 6}; 
int (*ptr)[3] = a; 
printf("%d %d ", (*ptr)[1], (*ptr)[2]); 
++ptr; 
printf("%d %dn", (*ptr)[1], (*ptr)[2]);


So (* PTR)[1], (* PTR)[2] is equal to a[0][1], a[0][2].

Question 8:


int *f1(void) 
{ 
int x = 10; return &x; 
} 
int *f2(void) 
{ 
int *ptr; *ptr = 10; return ptr; 
} 
int *f3(void) 
{ 
int *ptr; ptr = malloc(sizeof *ptr); return ptr; 
}


Here is the problem of returning a pointer, generally speaking, the return pointer function, there must be a memory request operation such as malloc, passed in the pointer type, is the content of the pointer to make changes. If you want to modify the pointer itself, you pass in the pointer to the pointer.

Question 9:


int i = 3; int j; 
j = sizeof(++i + ++i); 
printf("i=%d j=%dn", i, j);


This test is actually sizeof, which I mentioned in this article. P =1637) sizeof if the expression is evaluated, then the expression will not be evaluated, that is, regardless of the addition or subtraction, sizeof is evaluated for I. On a 32-bit machine, this j should be 4.

I've extended the code to see if you can think of a result:


short m; int n; double dn; 
int j = sizeof ( m + n); 
int k = sizeof ( n + n); 
int l = sizeof ( m); 
int l2 = sizeof (m * m); 
int l3 = sizeof (m + dn); 
int l4 = sizeof (m + m);


The first ten questions:


void f1(int*, int); 
void (*p[2])(int*, int); 
int main(void) 
{ 
int a = 3; 
int b = 5; 
p[0] = f1; 
p[1] = f1; 
p[0](&a, b); 
printf("%d %d ", a, b); 
p[1](&a, b); 
printf("%d %dn", a, b); 
return 0; 
} 
void f1(int *p, int q) 
{ 
int tmp = *p; *p = q; q = tmp; 
}


The p array of function Pointers is a bit of a puzzle, but the other puzzle is that for arguments like int q, you don't change their contents. *p modifies what p points to.

Question 11:


void e(int); 
int main(void) 
{ 
int a = 3; 
e(a); 
putchar( ' n'); 
return 0; 
} 
void e(int n) 
{ 
if (n > 0) 
{ 
e( � n); 
printf("%d ", n); 
e( � n); 
} 
}


This problem oneself debug once completely understood, the main knowledge point is recursive call, in addition the pre - post self - subtraction operation return value problem.

Question 12:


typedef int (*test)(float*, float*); 
test tmp;


It is also a kind of problem that often appears, to do the analysis of the complex definition of pointer, in fact, K&R (5.12) also introduced how to interpret. For those unfamiliar, try practicing the bsearch, qsort, and signal functions in the standard library.

Question 13:


char p; 
char buf[10] = {1, 2, 3, 4, 5, 6, 9, 8}; 
p = (buf + 1)[5]; 
printf("%dn", p);


I'm at (link: http://sunxiunan.com/? P =1637) also mentioned the relevant knowledge, that is, p actually points to *(buf +1 + 5), written a bit more bizarre is p=5[buf +1]; The same thing.

Question 14:

Similar to problem 13, but also a bit weird array, (p += sizeof(int))[-1]; The same thing as *(p + sizeof(int) + (-1)).

Question 15:


int ripple(int n,  ... ) 
{ 
int i, j, k; 
va_list p; 
k = 0; 
j = 1; 
va_start(p, n); 
for (; j < n; ++j) 
{ 
i = va_arg(p, int); 
for (; i; i &= i  �  1) 
++k; 
} 
return k; 
} 
int main(void) 
{ 
printf("%dn", ripple(3, 5, 7)); 
return 0; 
}


This problem is also two things, one is the definition of the variable-argument function and how to implement it, va_arg will pull out 5,7 in turn. The other thing is that I &= I -1, which is actually the number of I's in the I binary form, every time you do that you subtract the 1 from the least significant bit. So 7 in binary is 111. The results of I &= I and 1, in turn, are 110,100, 000 (i.e., 0). In hacker 's Delights in this book introduces many similar techniques.

Question 16:


int counter(int i) 
{ 
static int count = 0; 
count = count + i; 
return count; 
} 
int main(void) 
{ 
int i, j; 
for (i = 0; i <= 5; i++) j = counter(i); 
printf("%dn", j); 
return 0; 
}


It's a piece of cake to know what static local variables really mean...


Related articles: