Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the programming habits of C language?

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "what are the programming habits of C language". Friends who are interested might as well take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what are the C language programming habits"?

Judge failure rather than success

Here is a simplified code snippet:

If (physap_alarm_init () = = RV_SUCC) {if (trx_alarm_init () = = RV_SUCC) {if (bucket_init () = = RV_SUCC) {if (main_bhp_init () = = RV_SUCC) {/ * normal code * /} else {/ * error code * /}} else {/ * error code * /}

You can see that after the above code adopts the strategy of judging success, the nesting between if and else in the code is very chaotic, which is very unintuitive, and it is difficult to read the code. However, if the strategy of judging failure is adopted, the code will look concise. The following is the code that is improved by using the strategy of judging failure:

If (physap_alarm_init ()! = RV_SUCC) {/ * error handling * / return;} if (trx_alarm_init ()! = RV_SUCC) {/ * error handling * / return;} if (bucket_init ()! = RV_SUCC) {/ * error handling * / return } if (main_bhp_init ()! = RV_SUCC) {/ * error handling * / return;} / * normal code * /

As you can see from the above code, the changed code eliminates if nesting statements and greatly improves the readability of the code. It is important to note that not all cases can be better than successful strategies by judging failure strategies, which depends on the situation.

Using sizeof to reduce memory Operation errors

When writing code, we often involve initializing memory with the memset function at zero. Here are several examples of errors:

/ / example1 char * buf [Max _ LEN + 1]; memset (buf, 0, MAX_LEN + 1)

The error in the above code forgets that buf is an array of character pointers, not an array of characters

Continue to look at a piece of code:

/ / example2 # define DIGEST_LEN 17 # define DIGEST_MAX 16 char digest [DIGEST_MAX]; memset (digest, 0, DIGEST_LEN)

The error of the above code is the misuse of macros, although the error is relatively low-level, but also the possibility of making mistakes is quite high.

The last example:

/ / example3 dll_node_t * p_node = malloc (sizeof (dll_node_t)); if (p_node = = 0) {return;} memset (p_node, 0, sizeof (dll_t))

The error in the above code is that it is allocated with the size of the dll_node_t type, while the later memset () takes the size of the dll_t type, resulting in an error.

To reduce errors, the following code uses sizeof to avoid memory errors. First, take a look at the improved version of routine 1:

Char * buf [MAX_LEN + 1]; memset (buf, 0, sizeof (buf))

Next, take a look at the improved version of the sample 2 code:

# define DIGEST_LEN 17 # define DIGEST_MAX 16 char digest [DIGEST_MAX]; memset (digest, 0, sizeof (digest))

An improved version of example 3:

Dll_node_t * p_node = malloc (sizeof (* p_node)); if (0 = = p_node) {return;} memset (p_node, 0, sizeof (* p_node))

Summary

A small conclusion can be drawn from the above code that when using sizeof, take the name of the target variable that needs to be initialized as the parameter of sizeof (). It can be reduced to two rules:

When the target variable is an array, the memory size is obtained in the format of sizeof (variable name).

When the target variable is a pointer, the size of the memory is obtained in the format of sizeof (* pointer variable name).

Although the above example uses the memset function to introduce sizeof, this method can be run anywhere you need to get the memory size of a variable.

Masking programming language features

Array is a frequently used function in programming. The following is a simplified code that uses an array to save a session ID:

# define SESSION_ID_LEN_MIN 1 # define SESSION_ID_LEN_MAX 256 char g _ session ID [session _ ID_LEN_MAX]; int save_session_id (char * _ session_id, int _ length) {if (_ length)

< SESSION_ID_LEN_MIN || _length >

SESSION_ID_LEN_MAX) {return ERROR;} memcpy (g_SessionId, session_id, _ length); g_SessionId [_ length] ='\ 0mm; return SUCESS;}

At first glance, the above code may seem fine, but in the first if statement, when _ length equals SESSION_ID_LEN_MAX, the array is actually out of bounds, so the above code is actually problematic, and when you change it, you may change it in the following way.

If (_ length

< SESSION_ID_LEN_MIN || _length >

= SESSION_ID_LEN_MAX) {return ERROR;}

There is no logical problem with making changes in this way, but the code becomes less intuitive. SESSION_ID_LEN_MAX literally means the maximum length of the session ID, so this maximum length should be accessible, but here when _ length equals SESSION_ID_LEN_MAX, the array overflows. When you see > = when you look at the code, you basically need to stop and think about it. Thinking about why it can't be equal to SESSION_ID_LEN_MAX can't be understood intuitively, so in order to understand the code better and smoothly, you can modify the code like this:

# define SESSION_ID_LEN_MIN 1 # define SESSION_ID_LEN_MAX 256 / * make changes here * / char g _ session ID [session _ ID_LEN_MAX + 1]; int save_session_id (char * _ session_id, int _ length) {if (_ length)

< SESSION_ID_LEN_MIN || _length >

SESSION_ID_LEN_MAX) {return ERROR;} memcpy (g_SessionId, session_id, _ length); g_SessionId [_ length] ='\ 0mm; return SUCESS;}

Through the above change, that is, to subtract the value of SESSION_ID_LEN_MAX by one, the value of _ length can be taken to SESSION_ID_LEN_MAX at this time, and the code will be more intuitive to read.

Appropriate use of goto statements

There are multiple error handling codes, as follows:

Int queue_init (queue * * _ pp_queue, int _ size) {pthread_mutexattr attr; queue * queue; queue = (queue_t *) malloc (sizeof (queue_t)); if (0 = = queue) {return-1;} * _ pp_queue = queue; memset (queue, 0, sizeof (* queue)); queue- > size_ = _ size; pthread_mutexattr_init (& attr) If (0! = pthread_mutex_init (& queue- > mutex_, & attr)) {pthread_mutexattr_destroy (& attr); free (queue); return-1;} queue- > messages_ = (void**) malloc (queue- > size_ * sizeof (void*)); if (0 = = queue- > messages_) {pthread_mutexattr_destroy (& attr); free (queue) Return-1;} if (0! = sem_init (& queue- > sem_put_, 0, queue- > size) {free (queue- > message_); pthread_mutexattr_destroy (& attr); free (queue); return-1;} pthread_mutexattr_destroy (& attr); return 0;}

From the above code, we can see that it is easy to miss when handling errors, and the code looks bloated. Here is the code after using the goto statement:

Int queue_init (queue * * _ pp_queue, int _ size) {pthread_mutexattr attr; queue * queue; queue = (queue_t *) malloc (sizeof (queue_t)); if (0 = = queue) {return-1;} * _ pp_queue = queue; memset (queue, 0, sizeof (* queue)); queue- > size_ = _ size; pthread_mutexattr_init (& attr) If (0! = pthread_mutex_init (& queue- > mutex_, & attr)) {goto error;} queue- > messages_ = (void**) malloc (queue- > size_ * sizeof (void*)); if (0 = = queue- > messages_) {goto error;} if (0! = sem_init (& queue- > sem_put_, 0, queue- > size)) {goto error1 } pthread_mutexattr_destroy (& attr); return 0; error1: free (queue- > messages_); error: pthread_mutexattr_destory (& attr); free (queue); return-1;}

You can see that after using goto, the code becomes more readable. You should also pay attention to the following two principles when using goto:

Can't be abused.

Do not let the goto statement form a ring. The use of goto statements should form a line

Rational use of arrays in a multitasking programming environment, the life cycle of some tasks is the same as that of the whole program. They are created when the program is initialized and then run to the end of the program. For such a task, we call it a global life cycle, if a task with a global life cycle requires memory resources We can define global or static arrays instead of dynamic allocation. Here is the code to initialize the global variable g_aaa_eap_str_buff using malloc:

# define MAX_AAA_SS_PORTS 64 # define MAX_NUM_PADIUS_IDS (MAX_AAA_SS_PORTS * 256B) # define MAX_EAP_MESSAGE_LEN 4096 static char * * void thread_authenticator aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa If (0 = = g_aaa_eap_str_buff) {log_error ("Failed to allocate buffer for storing eap string"); return;} for (int I = 0; I < MAX_NUM_PADIUS_IDS; iTunes +) {g_aaa_eap_str_buff [I] = (char *) malloc (MAX_EAP_MESSAGE_LEN) If (0 = = g_aaa_eap_str_buff [I]) {log_error ("Failed to allocate buffer for storing eap string");} while (1) {...}}

The above code is to dynamically obtain memory through malloc, a better way is to use arrays to obtain memory, and one of the benefits of this is that the release of memory does not need our control, which reduces the possibility of memory leakage. The following is a code example:

# define MAX_AAA_SS_PORTS 64 # define MAX_NUM_PADIUS_IDS (MAX_AAA_SS_PORTS * 256) # define MAX_EAP_MESSAGE_LEN 4096 char g_aaa_eap_str_buff [MAX_NUM_PADIUS_IDS] [MAX_EAP_MESSAGE_LEN]; void thread_authenticator (void * _ arg) {while (1) {. }}

You can see that after using the array, the code becomes much simpler, but there is also one thing to note: because once the global or static array is defined, the memory it occupies cannot be released during the runtime. Therefore, when using arrays to reserve memory, you need to pay attention to the problem of memory waste.

At this point, I believe you have a deeper understanding of "what are the programming habits of C language?" you might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report