为什么我的输出空白?

时间:2019-05-17 13:58:57

标签: c++ pointers

为什么我的输出空白?指针能够修改但无法读取。为什么?

#include <iostream>
using namespace std;

int main(){
    int a = 0;
    char *x1,*x2,*x3,*x4;
    x1 = (char *)&a;
    x2 = x1;x2++;
    x3 = x2;x3++;
    x4 = x3;x4++;
    *x1=1;
    *x2=1;
    *x3=1;
    *x4=1;

    cout <<"@" << *x1 << " " << *x2 << " " << *x3 << " " << *x4 << "@"<<endl ;
    cout << a << endl;
}
[Desktop] g++ test_pointer.cpp
[Desktop] ./a.out
@   @
16843009

我想通过使用char的指针类型来读取integer的值。 这样我就可以逐字节读取。

5 个答案:

答案 0 :(得分:6)

您正在流char。 IOStreams *会自动为您提供ASCII码,因此you're seeing (or rather, not seeing) unprintable characters(实际上是所有0x01字节)。

您可以强制转换为int来查看数值,也可以为常规视图添加std::hex

示例:

#include <iostream>
#include <iomanip>

int main()
{
    int a = 0;

    // Alias the first four bytes of `a` using `char*`
    char* x1 = (char*)&a;
    char* x2 = x1 + 1;
    char* x3 = x1 + 2;
    char* x4 = x1 + 3;

    *x1 = 1;
    *x2 = 1;
    *x3 = 1;
    *x4 = 1;

    std::cout << std::hex << std::setfill('0');
    std::cout << '@' << std::setw(2) << "0x" << (int)*x1
              << ' ' << std::setw(2) << "0x" << (int)*x2
              << ' ' << std::setw(2) << "0x" << (int)*x3
              << ' ' << std::setw(2) << "0x" << (int)*x4
              << '@' << '\n';
    std::cout << "0x" << a << '\n';
}

// Output:
//   @0x01 0x01 0x01 0x01@
//   0x1010101

live demo

那些说您的程序未定义的说法是错误的(假设您的int中至少有四个字节);明确允许通过char*给对象起别名。

16843009输出正确;等于0x01010101,如果您将流设置为十六进制模式,您将再次看到它。


有些人会推荐reinterpret_cast<char*>(&a)static_cast<int>(*x1)而不是C样式的强制类型转换,尽管我个人觉得它们在这种特殊情况下很丑陋和不必要。对于输出,您至少可以编写+*x1来获得对int的“免费”升级(通过一元+运算符),但这并不是很容易自我记录。


*从技术上讲,情况恰恰相反。 IOStreams 通常通常会自动将您的数字,布尔值和其他内容转换为正确的ASCII字符,以便在屏幕上正确显示。对于char,如果您已经提供了所需的ASCII值,它将跳过该步骤。

答案 1 :(得分:2)

假设int在您的系统上至少有4个字节长,则程序将操纵int a的4个字节。

结果168430090x01010101的十进制值,所以这是您所期望的。

在输出的第一行中看不到任何内容,因为您写入了二进制值1(或0x01)的4个字符,它们是不可见的字符(ASCII SOH)。

当您像这样修改程序时

*x1='1';
*x2='3';
*x3='5';
*x4='7';

您将看到带有预期字符的输出

@1 3 5 7@
926233393

9262333930x37353331的十进制表示形式,其中0x37是字符'7'等的ASCII值。

(这些结果对小端架构有效。)

答案 2 :(得分:1)

看看您对x的声明

char *x1,*x2,*x3,*x4;

这些是指向chars(字符)的指针。

在流输出中,它们被解释为可打印字符。 简短浏览ascii-Table,您会发现较低的数字不可打印。

由于您的int a为零,所以指向各个字节的x也为零。

获得可读输出的一种可能性是将字符转换为int,以便流将打印数字表示形式而不是ascii字符:

cout <<"@" << int(*x1) << " " << int(*x2) << " " << int(*x3) << " " << int(*x4) << "@"<<endl ;

答案 3 :(得分:0)

如果我正确理解了您的问题,这就是解决方案

#include <stdio.h>
#include <iostream>
using namespace std;

int main(){
    int a = 0;
    char *x1,*x2,*x3,*x4;
    x1 = (char*)&a;
    x2 = x1;x2++;
    x3 = x2;x3++;
    x4 = x3;x4++;
    *x1=1;
    *x2=1;
    *x3=1;
    *x4=1;
    cout <<"@" << (int)*x1 << " " << (int)*x2 << " " << (int)*x3 << " " << (int)*x4 << "@"<<endl ;
    cout << a << endl;
}

答案 4 :(得分:0)

您可以使用一元+将字符类型(打印为符号)转换为整数类型(打印为数字):

cout <<"@" << +*x1 << " " << +*x2 << " " << +*x3 << " " << +*x4 << "@"<<endl ;

请参见integral promotion