简体   繁体   中英

What does (*(int *)&(w)) mean in c programming?

I'm learning processes and in the following code snippet:

/* 
 * fork10 - Synchronizing with multiple children (wait)
 * Reaps children in arbitrary order
 * WIFEXITED and WEXITSTATUS to get info about terminated children
 */
void fork10()
{
    pid_t pid[N];
    int i, child_status;

    for (i = 0; i < N; i++)
    if ((pid[i] = fork()) == 0) {
        exit(100+i); /* Child */
    }
    for (i = 0; i < N; i++) { /* Parent */
        pid_t wpid = wait(&child_status);
        if (WIFEXITED(child_status))
            printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status));
        else
            printf("Child %d terminate abnormally\n", wpid);
    }
}

when I trace WIFEXITED function definition this is what I've got:

#define WIFEXITED(x)    (_WSTATUS(x) == 0)
#define _WSTATUS(x) (_W_INT(x) & 0177)
#define _W_INT(w)   (*(int *)&(w))  /* convert union wait to int */

I have two questions:

  1. Why use mask 0177 instead of 0b1111111 , I've seen it many times, what's the benefits of using octal number over other formats? Personally I find binary more intuitive.
  2. What's the meaning of (*(int *)&(w)) ?

Thanks!

Binary constants such as 0b1111111 are not defined by the C standard and were introduced as an extension by some C implementations somewhat late, so earlier code necessarily used octal and hexadecimal constants, and programmers became accustomed to them. Additionally, octal is more compact, and I can count the number of set bits in 0177 more easily than in 0b1111111 . One quickly becomes accustomed to knowing that 7 means three bits set.

In (*(int *)&(w)) , &(w) takes the address of the object designated by w . Then (int *) converts that address from the type “pointer to type of w” to “pointer to int”. Then * dereferences that pointer, nominally producing an int value.

The intent is to access the first bytes of w as if they were an int , effectively getting the raw bits that are in w instead of interpreting it as a structure or whatever other type it is. This is called aliasing .

Aliasing in this way is not supported by the C standard, but many C implementations allow it, and the code you show appear to have been written specifically for such an implementation.

A supported way to get the raw bits of an object is to copy bytes individually, as with:

int b;
memcpy(&b, &w, sizeof b);

Although this looks like a function call, good compilers recognize it as a request to access the first bytes of w as if they were an int and optimize it. The result may be a single load instruction. However, wrapping this into a macro that produces the int as a value involves some complications, which I will leave for further discussion elsewhere. (You can ask a new question about that, if desired.)

1 Why use mask 0177 instead of 0b1111111 ... ?

(This answer only addresses this portion of your question)

Because 0b1111111 is not a C integer constant per 6.4.4.1 Integer constants :

Syntax

1

 integer-constant: decimal-constant integer-suffixopt octal-constant integer-suffixopt hexadecimal-constant integer-suffixopt decimal-constant: nonzero-digit decimal-constant digit octal-constant: 0 octal-constant octal-digit hexadecimal-constant: hexadecimal-prefix hexadecimal-digit hexadecimal-constant hexadecimal-digit hexadecimal-prefix: one of 0x 0X nonzero-digit: one of 1 2 3 4 5 6 7 8 9 octal-digit: one of 0 1 2 3 4 5 6 7 hexadecimal-digit: one of 0 1 2 3 4 5 6 7 8 9 abcdef ABCDEF integer-suffix: unsigned-suffix long-suffixopt unsigned-suffix long-long-suffix long-suffix unsigned-suffixopt long-long-suffix unsigned-suffixopt unsigned-suffix: one of u U long-suffix: one of l L long-long-suffix: one of ll LL

Description

2 An integer constant begins with a digit, but has no period or exponent part. It may have a prefix that specifies its base and a suffix that specifies its type.

3 A decimal constant begins with a nonzero digit and consists of a sequence of decimal digits. An octal constant consists of the prefix 0 optionally followed by a sequence of the digits 0 through 7 only. A hexadecimal constant consists of the prefix 0x or 0X followed by a sequence of the decimal digits and the letters a (or A) through f (or F) with values 10 through 15 respectively.

By standard, C only supports decimal, octal, and hexadecimal integer constants.

    1. It has the advantage of not requiring any extra symbols as digits (the hexadecimal system is base-16 and therefore needs six additional symbols beyond 0–9). It is also used for digital displays.
  1. You are trying to convert it to integer pointer and referencing the value from it.

About your first question: Binary literals are not officially part of the C standard (and are only part of C++ since C++14), hence using octal literals instead of using them can improve portability.

About your second question: &w takes the address of w , which is then converted to a pointer to an int ( (int*)&w ) which is dereferenced. What that effectively does is read memory from w as though w were an int .

you should check this link it will help you to solve any question by using (Clockwise/Spiral Rule)

http://c-faq.com/decl/spiral.anderson.html?fbclid=IwAR3V_KR4VwO33UvbO4LgN3AIW_79QBWAR9qHO2KHyyJgEuIKiFQOQTCec5U

( (int )&(w)) firstly &w means address of w where & is address operator then (int *) means creating pointer to integer so ( till this step you have pointer which point to address of w) finally * before this pointer means (you accessed the value of w )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM