&和|如何在C的这个例子中工作?

时间:2019-01-09 18:12:12

标签: c

我正在尝试这个示例,但我不明白这些值的显示方式。如果未初始化值,按位运算如何完成?

int main() {
  int a, b, c, d;
  d = a % b;
  c = a | b;
  printf("OR: %d", c);
  printf("AND: %d", d);
  return 0;
}

2 个答案:

答案 0 :(得分:3)

一个未初始化的变量包含垃圾值,使用它可能会变成undefined behavior。成为scared

甚至在按位运算之前,保存这些变量的存储器位置或寄存器也具有某些内容(通常无法预测)。认为该内容至少是随机的(或“无聊的”)。

顺便说一句,编译时应启用所有警告和调试信息。对于GCC,请使用gcc -Wall -Wextra -g。您的源代码可能会触发一些警告。我建议总是 初始化automatic variables(也许optimizing compiler会发现初始化是无用的,然后根据as-if rule跳过它;但是您确保该变量具有一些众所周知的值。

想象一下,您在另一台非常不同的计算机上(使用另一个操作系统,另一个编译器和另一个处理器)编译并运行相同程序。您很可能会观察到不同的程序行为。

答案 1 :(得分:1)

不知道您使用的编译器是什么,很难知道结果是什么,但是最有可能是0或一些

关于C的美丽之处之一是,您可以生成一种人类可以理解的汇编语言,并使用它可以看到C代码的作用。

我使用了ARM编译器,因为ARM CPU是精简指令集计算机(RISC),并且汇编代码更易于阅读。

为了编译代码,我运行了指令

arm-linux-gnueabi-gcc-7 -S -O0 -fverbose-asm  main.c

生成了一个main.s文件。 -S导致生成汇编代码。 -fverbose-asm将sorce代码添加为assmenly代码中的注释。 并且-O0阻止编译器将代码优化成更难阅读的内容。

您的OR代码生成:

@ main.c:7:  c = a | b;
        ldr     r2, [fp, #-8]   @ tmp115, a
        ldr     r3, [fp, #-12]  @ tmp116, b
        orr     r3, r2, r3      @ tmp114, tmp115, tmp116
        str     r3, [fp, #-16]  @ tmp114, c
@ main.c:8:  printf("OR: %d\n",c);
        ldr     r1, [fp, #-16]  @, c
        ldr     r3, .L3+4       @ tmp117,
.LPIC1:
        add     r3, pc, r3      @ tmp117, tmp117
        mov     r0, r3  @, tmp117
        bl      printf(PLT)     @

您的AND代码(通过将%替换为&进行了更正)将生成:

@ main.c:9:  d = a & b;
        ldr     r2, [fp, #-8]   @ tmp119, a
        ldr     r3, [fp, #-12]  @ tmp120, b
        and     r3, r3, r2      @ tmp118, tmp120, tmp119
        str     r3, [fp, #-20]  @ tmp118, d
@ main.c:10:  printf("AND: %d\n",d);
        ldr     r1, [fp, #-20]  @, d
        ldr     r3, .L3+8       @ tmp121,
.LPIC2:
        add     r3, pc, r3      @ tmp121, tmp121
        mov     r0, r3  @, tmp121
        bl      printf(PLT)     @

要解决您的问题,不初始化整数ab不会更改代码。 生成的汇编代码将使用frame pointerfp)减去8个字节和fp减去12个字节所指向的内存中的任何内容。 如果未将整数ab设置为特定值,则根据编译器的不同,您将获得随机值,或者对于某些编译器,您可能始终获得零值。

注意:您的C编译器可能会生成汇编代码。输出很可能是i386或X86汇编代码,但是您应该能够使用它来查看更改代码如何更改由编译器生成的代码。

这里是一个示例程序,该程序显示(至少使用gcc)不设置默认值会如何导致副作用。在这里,传递给一个子例程的值会影响另一个。

#include <stdio.h>

int first(int x, int y)
{
    int a, b, c, d;

    a = x;
    b = y;
}

int second()
{
    int a,b,c,d;
    c = a | b;
    printf("OR: %d\n",c);
    d = a & b;
    printf("AND: %d\n",d);
}

int main()
{
    first(5, 3);
    second();
    first(7, 5);
    second();
    return 0;
}

输出为

OR: 7
AND: 1

5和3以及

OR: 7
AND: 5

代表7和5。