
我有下面的程序:
int main(){
char* one = "computer"
char two[] = "another"
two[1]='b'
one[1]='b'
return 0
}
段错误发生在 "one[1]='b'"这一行上,这是有道理的,因为这个one指针指向的内存时只读内存。然而,问题是为什么 "two[1]='b'"这行没有发生段错误呢?查看gcc的汇编输出:
.file "one.c"
.section .rodata
.LC0:
.string "computer"
.LC1:
.string "another"
.text
.globl main
.type main, @function
main:
我们看到两个字符串都在 只读数据区域。那么为什么 “two[1]='b'”这行没有发生段错误呢?
one指针指向的stirng在只读页。另一方面,two是一个分配在栈上的数组,使用一些常量数据进行初始化。在运行期间,在只读区域的string会被拷贝一份到栈上。你修改的是string在栈上的拷贝,不是只读内存页。
更高层次的看法,从语言的视角看。“abcd”是一个const char*而不是 char*。因此,修改这样的指针值的结果是未定义的。这个语句char* one = "something",存储了一个指向字符串的指针(不安全的,它把const属性转换没了)。char two[] = "something"则是完全不同的。它实际上声明了一个数组并初始化了它,就像这样 int a[] = {1,2,3}。这里的引号里面的string是一个初始化表达式。
你看到的“another”在只读区域会被拷贝到数组 two中,在数组初始化的时候。另一方面,字符串“computer”的地址会被分配给one。
因此,one是指向只读区域(在这里写会发生段错误),two会分配在栈上然后拷贝一份“another”。
第二个形式会创建一个数组并拷贝这个字符串:
它等同于:
char two[] = {'a', 'n', 'o', 't', 'h'. 'e', r', '\0'}
你可以使用变量初始化字符数组,像这样:
char c = 'a'
char two[] = {'a', 'n', c, '\0'}
【int *ptr = NULL】与 【int *ptr = 0】是完全相同的。NULL即为0.这只是声明了一个指针变量,没有指向任何变量。
*** 作指针之前,要先检查其是否为NULL。if (!ptr) {...}
使用指针之前,给你分配空间,或者给其赋值(赋予某有效地址值)。
就是你的ptr = new int(0)
或者:
int n = 0
ptr = &n
printf("%s\n",p1)//p1代表的是字串首地址。*p="goodbye"
//编译时会出错。正确格式p="goodbye"
char
*func()
//函数指针的写法,返回一个指针,如库函数malloc,返回就是一段内存块的首地址。
你的程序是两次输出hello,如果要将指针内容更改,可以使用你说的这个格式char
*func()
#include
"stdio.h"
char
*func()
int
main()
{
char
*p1="hello"
printf("%s\n",p1)
/*
正确输出
hello,*p1的首地址
*/
p1=func()
/*
获得goodbye的首地址
*/
printf("%s\n",p1)
getch()
return
0
}
char
*func()
{
char
*p
return
p="goodbye"
/*将goodbye的首地址传回*/
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)