What is it for {} inside the main

3

I came across a C situation I do not know and had never seen anyone use before. Within the main() method there are several keys, I believe to isolate the code however there is a same variable that in each block of code receives a value and even changes type. The variable cfg appears several times, sometimes having type pjsua_config , sometimes having type pjsua_transport_config , sometimes having pjsua_acc_config type.

The code snippet has been taken from the tutorial that teaches you to use the pjsip library , the library is in C, would this be some way to simulate an inheritance (making a kind of cast )? Or to each block it creates a new variable and destroys the previous one?

I'm confused, I'm trying to pass some things to C ++, but I had trouble understanding that part.

int main(int argc, char *argv[])
{
    pjsua_acc_id acc_id;
    pj_status_t status;


    status = pjsua_create();
    if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);

    if (argc > 1) {
        status = pjsua_verify_url(argv[1]);
        if (status != PJ_SUCCESS) error_exit("Invalid URL in argv", status);
    }

    /* Init pjsua */
    {
         pjsua_config cfg;
         pjsua_logging_config log_cfg;

         pjsua_config_default(&cfg);
         cfg.cb.on_incoming_call = &on_incoming_call;
         cfg.cb.on_call_media_state = &on_call_media_state;
         cfg.cb.on_call_state = &on_call_state;

         pjsua_logging_config_default(&log_cfg);
         log_cfg.console_level = 4;

         status = pjsua_init(&cfg, &log_cfg, NULL);
         if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
    }

    /* Add UDP transport. */
    {
         pjsua_transport_config cfg;

         pjsua_transport_config_default(&cfg);
         cfg.port = 5060;
         status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
         if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
    }

    /* Initialization is done, now start pjsua */
    status = pjsua_start();
    if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);

    /* Register to SIP server by creating SIP account. */
    {
         pjsua_acc_config cfg;

         pjsua_acc_config_default(&cfg);
         cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
         cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
         cfg.cred_count = 1;
         cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
         cfg.cred_info[0].scheme = pj_str("digest");
         cfg.cred_info[0].username = pj_str(SIP_USER);
         cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
         cfg.cred_info[0].data = pj_str(SIP_PASSWD);

         status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
         if (status != PJ_SUCCESS) error_exit("Error adding account", status);
    }

    /* If URL is specified, make call to the URL. */
    if (argc > 1) {
         pj_str_t uri = pj_str(argv[1]);
         status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
         if (status != PJ_SUCCESS) error_exit("Error making call", status);
    }

    /* Wait until user press "q" to quit. */
    for (;;) {
         char option[10];
         puts("Press 'h' to hangup all calls, 'q' to quit");
         if (fgets(option, sizeof(option), stdin) == NULL) {
             puts("EOF while reading stdin, will quit now..");
             break;
         }

         if (option[0] == 'q')
             break;

         if (option[0] == 'h')
             pjsua_call_hangup_all();
    }

    /* Destroy pjsua */
    pjsua_destroy();

    return 0;
}
    
asked by anonymous 21.08.2018 / 22:06

2 answers

5

In fact, there's nothing wrong with it, it's just like what you've always used. It just demarcates the beginning and end of a block of code statements that should be considered in a unique way for some reason.

One problem I see a lot is that people do not understand what they use, hence the phrase I created:

  

As long as you do not know what each character in your code does, even white space, you still do not know how to program.

In this specific case it was used to keep certain variables within a specific scope because the block always generates a new scope. So all variables that were created inside it will not exist outside of it, and if there are variables outside of it with the same name, there is no confusion.

Then, in /* Init pjsua */ , the variable cfg , for example, is not the same variable cfg of /* Add UDP transport. */ or /* Register to SIP server by creating SIP account. */ . Same name, but different objects.

Learn more about What is the difference between scope and lifetime? .

It is no different from other uses such as in function, if , for , etc. You just did not know it was something that existed by itself.

In almost all situations it is demonstration of something wrong in the code and is not usually necessary. If this is used it should review the code, who knows how to separate parts into another function.

My cheer is that now start looking at everything in the code like other eyes and try to learn how things really are and not how they seem to be. Everyone would program better if they did this.

    
21.08.2018 / 22:13
1

It has no programmatic functionality besides separating the scopes (being able to declare variables of the same name with different types) and probably the author used to organize the code in the editor / IDE that he was using. As #region exists in C #.

    
21.08.2018 / 22:12