Sunday, 7 October 2018

What does _r suffix mean?


  • The suffix "_r" is historical, where the 'r' stood for "reentrant".
  • A computer program or subroutine is called reentrant.
    • if it can be interrupted in the middle of its execution and then safely be called again ("re-entered") before its previous invocations complete execution. 

  • Using global variable inside the function, ISR(interuppt call) may try to access our temporary changed global value in outside.
    • Solution:
      • Use the local variable instead of global variable will clear this issue
    • _r reason:
      • Using _r to make sure global variables are not affected.

  • _r function will be thread safe.
  • EG: strtok vs strtok_r



Return:
The strtok() and strtok_r() functions return a pointer to the next token, or NULL if there are no more tokens.

Attributes:
For an explanation of the terms used in this section, see attributes(7). ┌───────────┬───────────────┬───────────────────────┐ │InterfaceAttributeValue │ ├───────────┼───────────────┼───────────────────────┤ │strtok() │ Thread safety │ MT-Unsafe race:strtok │ ├───────────┼───────────────┼───────────────────────┤ │strtok_r() │ Thread safety │ MT-Safe │ └───────────┴───────────────┴───────────────────────┘

Program:


/* strtok vs strtok_r by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
    char *str1, *str2, *token, *subtoken;
    char *saveptr1, *saveptr2;
    char str_second[256] = {'\0'};
    int j;
    if (argc != 4) {
        fprintf(stderr, "Usage: %s string delim subdelim\n",
                argv[0]);
        exit(EXIT_FAILURE);
    }
    strncpy(str_second, argv[1], sizeof(str_second));
    printf("\n\n\t\t Do the token using strtok_r \n");
    /* use strtok_r */
    for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
        token = strtok_r(str1, argv[2], &saveptr1);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);
        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok_r(str2, argv[3], &saveptr2);
            if (subtoken == NULL)
                break;
            printf(" --> %s\n", subtoken);
        }
    }
    printf("Original value = %s \n", argv[1]);

    printf("\n\n\t\tDo the token using strtok str_second = %s \n", str_second);
    /* Initialize the variable to NULL to start token again with strtok */
    str1 = NULL;
    str2 = NULL;
    token = NULL;
    subtoken = NULL;
    saveptr1 = NULL;
    saveptr2 = NULL;
    /* use strtok */
    for (j = 1, str1 = str_second; ; j++, str1 = NULL) {
        token = strtok(str1, argv[2]);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);
#if 0 // Could not use the 2nd strtok with different delim because it uses the global pointer
        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok(str2, argv[3]);
            if (subtoken == NULL)
                break;
            printf(" --> %s\n", subtoken);
        }
#endif
    }
    exit(EXIT_SUCCESS);
}


Output:


learn$ ./a.out this,isvelraj,check,strok,new , .

                 Do the token using strtok_r
1: this
 --> this
2: isvelraj
 --> isvelraj
3: check
 --> check
4: strok
 --> strok
5: new
 --> new
Original value = this

                Do the token using strtok str_second = this,isvelraj,check,strok,new
1: this
2: isvelraj
3: check
4: strok
5: new

    No comments:

    Post a Comment