What is it for { } inside the main

Asked

Viewed 122 times

3

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

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

I confess that I am a little lost, because I am trying to pass some things to C++, but I had difficulty understanding this 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;
}
  • is used only to limit the scope, in each scope cfg is created and when closing the scope it dies, and in another scope it is "recreated" with another type (not the same variables, only has the same name)

  • The keys delimit scopes. When you do this, variables defined there within the scope only exist there. You can then define a variable with the same name several times, even of different types, without ambiguity if they are in scopes.

2 answers

6


Actually, he’s got nothing, he’s just like the one you’ve always used. It only demarcates the beginning and end of a code instruction blocks that should be considered in a unique way for some reason.

One problem I see a lot is that people don’t understand what they use, hence the phrase I created:

While you don’t know what each character of your code does, even white space, you still don’t 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 within 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 the /* Init pjsua */ the variable cfg, for example, not the same variable cfg of /* Add UDP transport. */ or of /* 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 as in the function, in the if, in the for, etc. You just didn’t know that 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 you use this you should review the code, maybe separate parts into another function.

My fan 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 that.

  • In fact, compound instruction is more or less common. Since RAII is a great language in C++, delimiting the lifetime of a state is done with these free scopes.

  • In linguistics code, yes.

  • @Maniero no use, even for this reason I came to ask what it was, the code as posted in the question is an example of the library developer himself. I agree that it is better to separate into other methods. But thank you for taking the doubt. I agree with your sentence when the code is yours, otherwise you can know how to program, but not have command of the syntax of a specific language. After all elaborate a cake recipe, it is also seen by many as a form of programming.

  • 1

    @Silenobrito If you don’t use your program in C, n]ao, you can’t even do Hello World without it. Without mastery of what he is doing in anything, one does not know how to do that, he is fooling himself that he knows. And I know that some people consider that cake recipe is programming, these people are the ones who don’t know how to program..

1

It has no programmatic functionality other than 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 he was using. How does the #region in c#.

  • 2

    It’s not like it’s the #region and was not used only to organize the code, in this case done without the block would give error.

  • 1

    I probably said, because in most IDE’s you can "compress" these blocks and keep the comments at the beginning of the block.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.