문제

I'm still learning about pointers. I know about switching up if statements and such. In the book i'm using, I was given this example:

    FILE* from = fopen("in.txt", "r");
    FILE* to = fopen("out.txt", "w");
    if (from != NULL && to != NULL)
    {
        ...
    }
    else
    {
        printf("failed to open files!\n");
    }
} /* end of function */

I know that can be changed to this:

    FILE* from = fopen("in.txt", "r");
    FILE* to = fopen("out.txt", "w");
    if (from == NULL || to == NULL)
    {
        printf("failed to open files!\n");
        return;
    }
    ...
} /* end of function */

Now, my question (if it will compile) is if this is safe or implementation defined as NULL is different on virtually every compiler.

    FILE* from = fopen("in.txt", "r");
    FILE* to = fopen("out.txt", "w");
    if ((from & to) == NULL)
    {
        printf("failed to open files!\n");
        return;
    }
    ...
} /* end of function */
도움이 되었습니까?

해결책

No.

First, it shouldn't compile, at least not if the compiler is standards-conformant. Pointers are not valid operands for bitwise operators like | and &.

Second, even if your compiler lets you treat pointers as integers, you risk platform incompatibilities; there are C implementations where they're not at all interchangeable. You might assume any such implementations would necessarily also be conformant, but assumptions are rarely safe...

Third, even assuming that ORing two pointers together works, and gets you something that you can compare with NULL, you've changed the sense of the test: (from|to) will only be NULL if both fopens failed; if just one of them succeeded, the result will be nonzero and your code will fail.

다른 팁

No.

For T *x and T *y in C, the expression x|y is meaningless, according to the standard. It should not compile. From n1256 §6.5.12 ¶2 "Bitwise inclusive OR operator":

Each of the operands shall have integer type.

This means that x|y is an error, end of story. The same applies to all other bitwise operators: & | ^ ~ << >> are all only usable on integers (note that "integers" include characters and bools).

However, if you want to save effort typing, it is perfectly valid to use logical operators on pointers.

// x == NULL is exactly semantically equivalent to !x
// These two are exactly the same
if (x == NULL || y == NULL) ...
if (!x || !y) ...

// In a logical expression, x != NULL is exactly semantically equivalent to x
// These two are exactly the same
if (x != NULL && y != NULL) ...
if (x && y) ...

It is up to you whether you think x == NULL is better or !x is better. You had better be able to read both, since both styles are common.

Don't ever try to play games with bitwise operators and pointers.

If you are just looking for a more terse way to write the expression, this is a pretty common and idiomatic way to do this:

    FILE* from = fopen("in.txt", "r");
    FILE* to = fopen("out.txt", "w");
    if (!from || !to) // note the use of the ! operator
    {
        printf("failed to open files!\n");
        return;
    }
    ...
} /* end of function */

The ! operator is a logical NOT operator. Since the null pointer always has a value of 0, which is a "false" value, the expression !from means "true if from is a null pointer, otherwise false`. It reads pretty well also: "if not from, or not to, then handle an error"

Likewise, people write code like if (from) to check if a pointer is non-NULL.

P.S. I know many people like to use expressions like FILE* when declaring pointers, but I dislike this form, because it is a lie. When you declare FILE *from this means "the expression *from has type FILE". It works to put the * right after the FILE but this makes it look like this means "the expression from has type pointer-to-FILE". It doesn't, and here's an example:

FILE* from, to;

from has type "pointer-to-FILE". What type is to? Why it is plain old FILE, not any sort of pointer. The expression you need to use, if you are declaring these on one line, is:

FILE *from, *to;

This means "the expression *from is type FILE, and the expression *to is type FILE." And it looks like it, once you are used to this.

You could write this, but it's icky.

FILE* from, *to;

Yuck!

from and to are pointers, you cannot do any bitwise operation on them. However, <stdint.h> provides intptr_t which is of integer type and is guaranteed to hold a pointer, so casting your pointers to them first would be valid. However, this is ugly, so I would stick with the more readable version.

Bitwise operation are not allowed on pointers.

You should avoid such exercise.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top