指针算术

时间:2012-06-29 03:52:55

标签: c pointers null null-pointer

我还在学习指针。我知道如何切换if语句等。在我正在使用的书中,我得到了这个例子:

    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 */

我知道可以改为:

    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 */

现在,我的问题(如果它将编译)是,如果这是安全的,或者实际定义为NULL几乎在每个编译器上都是不同的。

    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 */

5 个答案:

答案 0 :(得分:6)

没有

首先,它不应该编译,至少在编译器符合标准时不应该编译。指针不是|&等按位运算符的有效操作数。

其次,即使您的编译器允许您将指针视为整数,也存在平台不兼容的风险;有C实现,它们根本不可互换。您可能认为任何此类实现都必须符合要求,但假设很少是安全的......

第三,即使假设ORing两个指针在一起工作,并为你提供一些可以与NULL进行比较的东西,你已经改变了测试的意义:(from|to)只会{{1}如果两个 NULL都失败了;如果只有其中一个成功,结果将是非零的,您的代码将失败。

答案 1 :(得分:5)

没有

对于C中的T *xT *y,根据标准,表达式x|y毫无意义。它不应该编译。从n1256§6.5.12¶2“按位包含OR运算符”:

  

每个操作数都应具有整数类型。

这表示 x|y错误,故事的结尾。这同样适用于所有其他按位运算符:& | ^ ~ << >>全部可用整数(注意“整数”包括字符和bools)。

但是,如果您想节省工作量,那么在指针上使用逻辑运算符是完全有效的。

// 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) ...

您是否认为x == NULL更好或!x更好,取决于您。你最好能够同时阅读这两种风格,因为这两种风格都很常见。

答案 2 :(得分:1)

不要尝试使用按位运算符和指针来玩游戏。

如果您只是想要一种更简洁的方式来编写表达式,这是一种非常常见和惯用的方法:

    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 */

!运算符是逻辑NOT运算符。由于空指针的值始终为0,这是一个“假”值,因此表达式!from表示“如果from是空指针,则为true,否则为false。”它也读得很好: “如果不是来自或不来,则处理错误”

同样,人们编写类似if (from)的代码来检查指针是否为非NULL。

P.S。我知道很多人喜欢在声明指针时使用像FILE*这样的表达式,但我不喜欢这种形式,因为它是一个谎言。当您声明FILE *from时,这意味着“表达式*from具有类型FILE”。它可以将*放在FILE之后,但这使得它看起来像“表达式from具有类型指针 - FILE”。它没有,这是一个例子:

FILE* from, to;

from的类型为“指向 - FILE”。什么类型to?为什么它是普通的FILE,而不是任何类型的指针。如果要在一行中声明这些表达式,则需要使用的表达式为:

FILE *from, *to;

这意味着“表达式*from的类型为FILE,而表达式*to的类型为FILE。”一旦你习惯了,它看起来就好了。

你可以写这个,但它很吵。

FILE* from, *to;

呸!

答案 3 :(得分:0)

fromto是指针,你不能对它们进行任何按位操作。但是,<stdint.h>提供intptr_t,它是整数类型并且保证保持指针,因此首先将指针转换为它们是有效的。但是,这很难看,所以我会坚持使用更易阅读的版本。

答案 4 :(得分:0)

指针上不允许按位操作。

你应该避免这种运动。