第六章 Pointers

今天有点时间看看c和指针的第六章,真的是闲的没有事情干。。。

读完这一章我感觉稍微有点感想吧,由于以前用过很多次指针,所以书本上的知识都知道,所以我想在这里简单的总结一下,方便以后复习。。


首先我想提出一个问题:

1.如果把一个float类型的变量的地址复制给int类型的指针,无论使用不使用强制类型转化,之后再把int指针的值输出,请问会输出什么。

#include <stdio.h>
int main (void) {
    float a = 3.14;
    int *p = &a;
    printf("%d\n",p);
    return 0;
}

答案 :输出变成一个很大的数字。

为什么呢 ?

这是浮点数存储和int类型的存储不一样的问题。但是这不是我要说的问题,如果有人喜欢请看IEEE 754标准

我在提出一个问题:

2.如果把一个float类型的变量直接使用%d打印出来,不使用强制类型转换,会输出什么呢?

#include <stdio.h>
int main (void) {
    float a = 3.14;
    printf("a = %d\n",a);
    return 0;
}
为什么呢?

这也是浮点数和int类型存储不一样导致的,但是重点来了,如果上面两个代码打出之后你会发现打印的数字不一样,为什么呢,引出了我第三个问题:

3.为什么一个float类型的变量给int类型指针使用%d打印出来的数字和float类型变量直接使用%d打印出来的数字不一样呢,同样的地址,同样的%d,为什么呢?

在这里我想说我也是花了一晚上的时间通过测试代码才想出来的,首先我们要知道如果打印乎float变量的二进制,不是float的地址啊,请注意,是float变量的二进制。

#include <stdio.h>
int main (void) {
    float a = 1;
    int i,s = 1;
    unsigned int *temp = (unsigned int* ) &a;
    for (i = 31;i >= 0;i--) {
        if((s<<i)&(*temp))
            printf("1");
        else
            printf("0");
        if(i == 31 || i == 31-8 )
            printf(" ");
    }
    printf("\n");
    return 0;
}

这个就能打印出a(float)变量的二进制。由于我使用了float 4个字节,使用unsigned int* 就可以保存下去,如果使用int* 也可以完整的保存float二进制。在这里我不想多说。

接着我猜想到。

#include <stdio.h>
int main (void) {
    int i,s = 1;
    float a = 3.14;
    int *p = (int*) &a;
    unsigned int *pu = (unsigned int*) &a;
    printf("使用的int指针\n");
    for (i = 31;i >= 0;i--) {
        if ((s<<i) & (*p))
            printf("1");
        else
            printf("0");
        if (i == 31 || i == 31-8) printf(" ");
        i == 0 && printf("\n");
    }
    printf("p = %d\n",*p);
    printf("使用的unsigned指针\n");
    for (i = 31;i >= 0;i--) {
        if ((s<<i) & (*pu))
            printf("1");
        else
            printf("0");
        if (i == 31 || i == 31-8) printf(" ");
        i == 0 && printf("\n");
    }
    printf("pu = %u\n",*pu);
    printf("a = %d\n",a);
    printf("sizeof(float) = %d\n",sizeof(a));
    printf("sizeof(int) = %d\n",sizeof(int));
    return 0;
}

我分别使用int 和 unsigned int两种类型打印出float a 变量的二进制,发现都是一样的,但是只要是使用a直接打印就发现和他们表示的数字是不一样的,我突然想到,如果一个float类型+一个int类型会经过隐式类型的转换,之后我写出代码。

#include <stdio.h>
int main (void) {
    double a = 1;
    printf("sizeof(long long) = %d\n",sizeof(long long));
    printf("sizeof(double) = %d\n",sizeof(double));
    printf("sizeof(unsigned long long) = %d\n",sizeof(unsigned long long));
    long long *p = (long long *) &a;
    unsigned long long *pu = (unsigned long long *) &a;
    int i,s = 1;
    for (i = 63;i >= 0;i --) {
        if ((s<<i) & (*p))
            printf("1");
        else
            printf("0");
        if (i == 63 || i == 63-11) printf(" ");
        i == 0 && printf("\n");
    }
    for (i = 63;i >= 0;i--) {
        if ((s<<i) & (*pu))
            printf("1");
        else
            printf("0");
        if (i == 63 || i == 63-11) printf(" ");
        i == 0 && printf("\n");
    }
    printf("p = %lld\n",*p);
    printf("pu = %llu\n",*pu);
    printf("a = %lld\n",a);
    return 0;
}

发现和我想到的一样,最后我得到答案就是 在使用a变量直接%d打印的时候a变量由于是float类型他如果要int类型打印的话,需要进行隐式类型的转换,所以他会先转换成double类型,之后再进行打印,由于double类型是8个字节,int类型只能打印出其后4个字节的内容,但是如果使用了把float变量的地址给int类型的指针的时候就不会出现这个问题,他们会把float类型的地址直接打印出来,不会有舍弃的位数。

虽然能这样说,但是你直接使用一个指向float变量的int指针之后给他做移31,之后%d打印出来和float变量%d打印出来的数字还是有些区别的,我想是由于float在转化成double类型的时候还是有一些区别的。


这写问题只是我突然看到这c和指针第六章突然想到的,我还没有说完,还有问题:

4.操作符的使用次数问题。

给你一段代码你判断一下会输出什么。

#include <stdio.h>
int main (void) {
    char c = 'a';
    char *pc = &c;
    printf("pc = %c\n",++*pc++);    
    return 0;
}
你要是看到这个代码如果不打印代码的话,你能说出来他会输出什么么,我一开始看到这个时候我有点蒙了,后来要是通过代码测试想到的。

随便说一下,在printf结束后pc的指向和c变量内容的变化。


在这里我想说明的是操作符的分类性(这个名词好像不太明白,这个我也是想出来的,我不知道应该如何说才会具体一点,毕竟从小到大语文都不及格的。)


最后printf输出 ‘b'

pc会指向c变量地址的后一个地址。相当于c变量地址自加。

在这里我是这样想的,高优先级的在一起执行,低优先级的在一起执行。


如果是这个代码你会怎么想:

#include <stdio.h>
int main (void) {
    char c = 'a';
    char *pc = &c;
    printf("pc = %c\n",++(*pc)++);
    return 0;
}

这个输出就有一点不一样了。你能想象输出么。

结果是编译错误,有没有想到啊,反正我是没有想到。

这个出现的错误一般就是

lvalue required as increment operand

意思就是 右值不能前置

也叫ub = “未定义行为”

这个出现的问题在于

前++ 不能给左值进行自加行为导致的。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值