x86 上的指针大小和奇怪的字符输出

Pointer size on x86 and weird characters output

本文关键字:字符 输出 指针 x86      更新时间:2023-10-16
#include <iostream>
#define SIZE 2
int main(int argc, char** argv)
{
char w = 'a';
char *array[SIZE];
array[0] = &w;
std::cout << *array << std::endl;
system("PAUSE");
return(0);
}

程序的输出为:a╠╠╠╠┴Kôè∞≈5«,┌

Char 是一个字节长,因此输出应为:a

或者它输出垃圾,因为 x86 的指针大小为 4 个字节(对于 int、double、float、char),而所有垃圾都是这 3 个字节?

char *array[SIZE];

您正在声明一个字符指针数组,该数组的每个元素都是一个字符*, 然后

char[0] = &w;

您正在为第 0 个指针分配变量 w 的地址。

std::cout<<*array<<std::endl;

std::cout<<array[0]<<std::endl;

您正在尝试打印第 0 个指针,您将其设置为不以 null 结尾的字符串,当您从内存中读取随机内容时,任何事情都可能发生。

这与指针大小或内置类型的大小无关。

代码将字符的地址存储在array[0]中,然后将该地址发送到std::cout。将char*插入std::cout时,插入器假定指针指向以 nul 结尾的字符数组。这里没有 NUL 终止符,所以它继续写东西,直到它达到零。从形式上讲,行为是未定义的。

你会得到同样的东西,更清楚地,char* array = &w; std::cout << array << 'n';.或者,更简单,std::cout << &w << 'n';.

若要写入字符的值,请使用std::cout << w << 'n';,或者,如果需要使用该数组,请在数组开头写出字符。这是array[0][0]或者,如果您喜欢直接取消引用,**array.

Char 是一个字节长,所以输出应该是:a

"一个字节"的长度尚未存储在已编译程序的任何地方。

指向一个字节的指针(如char *)与指向多个字节的指针没有什么不同。 指针不知道。

当您将字符指针发送到std::cout时,该流旨在输出连续字符,直到遇到空字符。 这就是确定应输出多少个字符的方式。 指针不知道,因此指向的数据应标记其结束。

表达式中使用的数组(极少数例外)将转换为指向其第一个元素的指针。

从C++标准(4.2 数组到指针的转换)

1 类型为"N T 数组"或"未知数组"的左值或右值 T"的绑定"可以转换为"指向T的指针"类型的prvalue。这 结果是指向数组第一个元素的指针。

所以在这个声明中

std::cout << *array << std::endl;

子表达式array具有char **类型,因为数组的元素具有 Char *的类型

。因此,表达式*array的类型为char *。并且您正在尝试输出指针*array指向的字符串,该字符串不是以零终止的。因此,该程序具有未定义的行为。它输出字符'a'后面的所有字符,直到内存中遇到零字符。

你需要写

std::cout << **array << std::endl;

仅输出一个字符。

这是一个演示程序

#include <iostream>
int main() 
{
const size_t SIZE = 2;
char w = 'a';
char *array[SIZE];
array[0] = &w;
std::cout << **array << std::endl;  
return 0;
}

它的输出是

a

此声明

std::cout << *array << std::endl;

如果在对象中的字符"a"之后有一个零字符,即语句将处理字符串,则可以正常工作。

例如

#include <iostream>
int main() 
{
const size_t SIZE = 2;
char w[] = { 'a', '' };
char *array[SIZE];
array[0] = &w[0];
std::cout << *array << std::endl;   
return 0;
}

程序输出与上面的shwon相同。