Two problems related to C language make me feel depressed.

Source: Internet
Author: User

I. Assert () in the C standard library will roughly end the program

Assert () is compiled as an empty statement in the release program. It only exists in the debug program, and its intention is obvious, it is to promptly remind developers to pay attention to abnormal situations in the program, and assist developers to eliminate such abnormal situations, so that the program is gradually improved. In general, an Assert () Assert failure must be a branch in which the program's running state exceeds the programmer's expectation, or the program flow enters the stage where the code has not yet been processed. In this case, the programmer needs to analyze the assert () context to identify the root cause of the problem and improve the program. At this time, you can continue to execute several code statements to the next order to collect more information and help you solve the problem in a more timely manner. But what about assert () of the C standard library provided by Microsoft? After the assert fails, the program is not interrupted at the line of code that calls assert (), but is interrupted within the C Runtime Library, and the program is about to be aborted immediately. In the past, I used to get used to assert () in MFC. It allows the user to choose to suspend the program, ignore the assertions, and interrupt (can continue execution) after the assertions fail, which is very friendly to programmers. Now I am using assert () in the C standard library. The solution is to write a my_assert () by yourself. The Code is as follows:

//. H <br/> # If _ debug |! Ndebug <br/> # define my_assert (exp) do {If (! (Exp) {my_assert_failed (# exp, _ file __, _ line _); _ asm int 3 }}while (0) <br/> void my_assert_failed (const char * info, const char * file, unsigned int line ); <br/> # endif <br/> # ifdef ndebug <br/> # UNDEF my_assert <br/> # define my_assert (exp) (void *) (0) <br/> # endif <br/> //. c <br/> # If _ debug |! Ndebug <br/> void my_assert_failed (const char * info, const char * file, unsigned int line) <br/>{< br/> printf ("/007/nassert failed: % s/n at file/"% S/", % d line. /n ", info, file, line); <br/>}< br/> # endif <br/>

 

 

II. The simple rewrite of the For Loop is also faulty.

The following typical for loop code is overwritten, so you can no longer be familiar with it:

For (unsigned int I = 0; I <n; I ++ ){}

If n in the above code is not a constant or variable, but an expression (for example, P1-> P2-> N), then n will be evaluated once for each loop, it will undoubtedly increase the burden on the program and is inappropriate when the execution efficiency is very high. Generally, the for loop is slightly rewritten from the back to the back (applicable to situations where you don't mind the loop order), and the loop variable I is reduced from n-1 to 0:

For (unsigned int I = n-1; I> = 0; I --){}

 

However, the above for loop rewriting has a major defect, that is, when n is zero, its behavior is not "not to execute for loop", but "to execute for loop many times ". Because when n is zero, the initial value of loop variable I is (unsigned INT)-1, that is, 4294967295. This value is greater than zero, so the For Loop will always be executed, until I is reduced to 0. This behavior is different from the previous regular for loop behavior (when n is zero, the loop is not executed. The key lies in that the type of I is unsigned Int. If it is an int, there will be no problem (but if n is an unsigned integer, it would be too much trouble to define I as a signed integer ). It is easy to correct code errors. What I suppress is that I cannot find a better way to write code. I think of two solutions: solution 1. Evaluate N and put it in another variable M before for, and write the loop to for (unsigned int I = 0; I <m; I ++ ){}. Solution 2: Set a judgment statement, if (n! = 0) for (unsigned int I = n-1; I> = 0; I --){}. However, I don't always feel very satisfied. In general, solution 1 is a good solution, but it uses a variable to increase the space occupied by the stack. It is not suitable for a program that relies heavily on recursion, in the end, I chose solution 2, which is ugly, but I was always depressed because I didn't write beautiful code. Oh, my God! I finally found that solution 2 also has a major defect. I of the unsigned integer type is always greater than or equal to 0, the For Loop will never exit, and the endless loop! Helpless sacrifice solution 3: For (unsigned int I = N; I> 0; I --) {}, the cycle variable decreases from N to 0 (excluding 0 ). However, in the cycle of solution 3, I must be written into I-1 where I is used, and the additional computation is increased (originally, n is repeatedly evaluated for each loop, i-1 values for each loop), which is inconsistent with the original intention of rewriting the for loop.

It is uncomfortable to write beautiful code. Do I feel like I am in the dark? Is it unacceptable to define a variable in the stack to occupy 4 more bytes of memory? Is it unacceptable to calculate an addition or subtraction multiple times in a loop? It can be the same for me. If I use Java or easy language to write programs, I will never make the same mistake. The magic of programming languages is amazing.

 

 

  The following is a grand launch of zhxk82Another way of writing is provided in the comments after this article:

For (unsigned int I = n-1; I <(unsigned INT)-1; I --)

Haha, it's good. Everything except not very intuitive. Oh, I am not depressed now, and I feel very comfortable. Thank you, zhxk82.

 

 

Liigo note in the early morning of 9.8.21: As some comments have said, the second article is too trivial and too entangled in details. In fact, I don't want to optimize it too early, and I am more inclined to write intuitive code. I don't want to complicate things, and I am willing to believe that the compiler will handle it well. In the end, I switched the code back to the original for (unsigned int I = 0; I <n; I ++, however, there are still some emotions that cannot be relieved. Hi.

 

On the evening of 2009.8.22, liigo again declared: I wrote this article not to blame and complain about the C language, but to blame myself for failing to write beautiful, simple, and intuitive code (I don't know if you feel the same way, writing beautiful Code will make you feel comfortable ). This article expresses the depressed mood and releases the repressed mood. It is a self-relief method. In the end, I jumped out of the circle and said the somewhat Zen conclusion I have summarized over the years: when you use a programming language and access its community, it will be affected by its thinking model; when entering another field, the corresponding thinking mode will automatically switch. Different thinking modes may lead to different processes and results. I believe this is a relatively close-to-Objective Expression and not subjective.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.