分段错误和char指针以及int ponter

segmentation fault and char pointer and int ponter

本文关键字:int ponter 指针 错误 char 分段      更新时间:2023-10-16

code1:


char *pc = "abc";     
cout<<*pc<<endl;

代码2:


int *pi = 10 ;
cout<<*pi<<endl;

为什么code1提示warn消息为";警告:不赞成从字符串常量转换为"char*";;但code2提示error消息为"错误";错误:从"int"到"int*"的转换无效;。

【Q1】在我看来,它们都不匹配,但为什么一个得到警告,另一个得到错误?

当我尝试修复此问题时,如:

代码3:


int *pi = (int*)10 ;  //compile correctly without error
cout<<*pi<<endl;      //get "segmentation fault"

代码4:


char *pc = (char*)"abc";  //compile without warning    
cout<<*pc<<endl;         // output 'a'

【Q2】为什么cout<lt*pi<lt;endl在code3中得到分段错误和cout<lt*pc<lt;code4中的endl是否正确运行?

这似乎是一个受欢迎的问题,但很少有人解释其中的差异。有人能帮我吗?

提前谢谢。

  1. 尝试:

    const char *pc = "abc";     
    cout << pc << endl;
    
  2. 尝试:

    int pi = 10;
    cout << pi << endl;
    

在上面的情况1中,字符串文字的类型是const-char*

在情况2中,您声明的不是整数,而是一个整数指针,并将ADDRESS 10分配给该指针,然后尝试取消引用它(实际上,您试图访问内存地址10处的数据,而您可能无法访问该地址,这就是导致崩溃的原因)

虽然语法可能很危险,但这里的foo确实指向内存中的一个有效位置——它是指向"abc"(也称为"a")开头的字符指针:

char *foo = "abc";

但是这里:

int *pi = (int*)10 ;  //compile correctly without error
cout<<*pi<<endl;

pi指向内存地址10,这是可以的,直到你试图尊重它——这是一个很大的拒绝,因为你的程序无法访问该内存。

char *pc = "abc";

"abc"就是所谓的字符串文字。它可能不会像你所知道的那样存储在内存中,也可能无法更改。尝试,例如

pc[1] = 'k';

将产生不可预测的结果,很可能会因为无法写入该位置而导致程序崩溃。

编译器警告告诉您,您正在将一个指向不能或不应该更改的值的指针分配给一个允许您更改该值的指针。这里的快速解决方案是通知编译器,您不会尝试更改"abc",如果您尝试,则接受编译器的严厉批评。

const char *pc = "abc";

写入pc引用的内存现在会生成编译器警告,但这比程序写入无效内存并做一些奇怪的事情要好。

这是一个警告,而不是一个错误,因为有大量的古代代码正是执行这种有风险的常量->非常量赋值,但从不尝试写入不可写的位置,如果出现错误,就会停止编译。目前,编译器只需标记问题并建议您进行修复

此代码:

char *pc = (char*)"abc";  
cout<<*pc<<endl;         

不会崩溃或表现出不良行为,因为保存"abc"的位置是可读的。

char *pc = (char*)"abc";  
cin >>*pc;         

如果不是立即致命的话,那将是非常糟糕的。

另一方面,

int *pi = 10 ;

有点不同。它将指针指向内存位置10处的整数,这几乎肯定是错误的。虽然char *pc = "abc";有风险,但尝试使用尚未分配给程序的内存位置是不好的,可能是致命的。你希望它是致命的,因为另一种选择是一个不那么有趣的游戏,"老兄,我的数据在哪里?"指针不是整数,不管你可能被告知什么,而这会导致错误,这迫使程序员在做愚蠢的事情之前至少要思考。

在驱动程序和嵌入式编程中,直接硬件访问是常见的,但这些都是通过强制转换和其他技巧指定的,以确保编译器知道你在做什么,并且在指定的地址确实存在可访问的东西。正是你在这里所做的:

int *pi = (int*)10 ;

但是,当你试图打印它时,程序会崩溃,因为在地址10没有为你的程序分配和访问任何内容。正如你所看到的,这被认为是一个有充分理由的错误。你既不能读也不能写,所以它不会得到编译器为可读但不可写的"abc"提供的条件传递。