一个c语言字符指针问题!

char*ch;ch="abcdefg";为什么不能这样修改?:*(ch+1)='a';char**x,str[20][100]={""};这个x可以直接指向str吗?:... char *ch;
ch="abcdefg";
为什么不能这样修改?:*(ch+1)='a';

char **x,str[20][100]={""};
这个x可以直接指向str吗?:x=str ;
但是这样会出错:*(*(x+2)+3)='1';
为什么???求详细解释!!!
展开
 我来答
海狮2D
2012-05-02 · TA获得超过3019个赞
知道大有可为答主
回答量:1904
采纳率:55%
帮助的人:995万
展开全部

看了目前的回答,觉得还不完整。

1、为什么不能修改:

其实不一定,不让修改是一种保护。

Linux kernel前一阵子报告的严重问题的就是可以修改这个东西了。

如果能够修改,这个ch="abcdefg"的语义就不正确了。

因为,假设如果有下面的程序:

ch="abcdefg";

printf("%s\n",ch);

如果按照正常理解,应当总是打印"abcdefg",但是如果你刚才的那个能够执行,那可就不是了。

看看下面的程序:

bug:

ch="abcdefg";

printf("%s\n",ch);

*(ch+1)='a';

goto bug;

那岂不是第一次打印"abcdefg",后面都是打印"aacdefg",如果这样也可以,C语言的程序就没办法看了。

理论上,这种错误很明显,所以一般的编译器会检查出来,说编译器检查不到的说法是错误的。但是因为C语言是弱类型语言,检查出来也不汇报告,换做C++就不行了,会告诉你,ch="abcdefg",这句话有问题。因为"abcdefg"是一个const char [8],但是ch是一个 char *这种转换很危险。

---------------------------------------------------------

2、复制不行,类型不匹配,很多书上在这个问题上写的都不对。

数组类型不是指针类型,差别很多。

举个例子:

这个会报错

char *ch="abcdefg";

*(ch+1)='a';

这个呢

char ch[10]="abcdefg";

*(ch+1)='a';

先说说一维数组的类型:

char ch[10];

ch的指针的类型是 

char (*p)[10];

p=&ch;

所以能够和str赋值的x的类型是:

char (*x)[100];

x=str;

或者说指针没有长度,而数组有,怎么赋值呢?

更多追问追答
追问
但是为什么这样又可以修改呢?:
char *ch;
ch=(char *)malloc(20);
strcpy(ch,"abcdefg");
*(ch+1)='a';
puts(ch);
这样的话输出就是aacdefg了?何解?
追答
这个你还要慢慢学。
一般来说,堆上和栈上的东西是可以修改的。
malloc会在堆上创建东西,千万不要忘记free!!!!!!!!!!!!!!!!!!!!!!!!!!
你现在这样做,很可能未来会因为这个丢了工作。
-------------------------------
类似的,堆上的操作包括:
char *ch=strdup("abcdefg"); ( 对于VC,有些版本要写成char *ch=_strdup("abcdefg"); )
free(ch);
未来如果学习C++,还包括new/delete等等。
--------------------------------
还有栈上的:
char ch[10]="abcedfg";
(也可以写成:char ch[10];strcpy(ch, “abcdefg");)
---------------------------------
无论堆上或者栈上,如果要显示字符串,都要经过复制的步骤,在你的程序里面就是strcpy。
复制的操作,是把一个const char *,转化成char *的步骤,你可以看看strcpy那个函数。
char * strcpy(char *dest, const char* src);
其中,src是不能修改的(const char *),而dest你复制完成后,变成了char *。这个步骤去掉了const 的约束。
此外,strdup是分配内存+复制,ch[10]="abcdefg"是栈上分配内存+复制,char ch[10];是栈上分配内存。
栈上的变量有时也叫做自动变量,分配和释放是自动的,堆上的典型的包括:malloc、calloc、strdup……,必须要配合free使用。不释放内存是写程序的最大忌讳之一。
394866351
2012-05-02 · TA获得超过124个赞
知道小有建树答主
回答量:276
采纳率:0%
帮助的人:205万
展开全部
第一问:
错误的原因很简单,因为编译器默认是把"abcdefg"放在代码段,代码段是不可写的,所以会出错,如果你想修改的话,建议这样声明 char s[]="abcdefg"; char *ch = s;

第二问:
可以这样
char **x;

char *p;

char str[20][100] = {"abcdefghijklmn"};

p = &str[0][0];

x = &p;

但是你操作不能这样操作*(*(x+2)+3) = '1'; 这样会修改其他变量的数据
应该改成*((*x+2*100)+3) = '1'; //相当于str[2][3]
追问
但是为什么这样又可以修改呢?:
char *ch;
ch=(char *)malloc(20);
strcpy(ch,"abcdefg");
*(ch+1)='a';
puts(ch);
这样的话输出就是aacdefg了?何解?
追答
ch指向a,(ch+1)指向b, *(ch+1)='a';表示把'b'替换成'a'
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
wanfustudio
2012-05-02 · TA获得超过1万个赞
知道大有可为答主
回答量:5513
采纳率:100%
帮助的人:3729万
展开全部
1。已知:常量不允许修改,间接修改编译器检查不到,运行时才会报错,常量字符串也是常量 你这里是通过地址,间接地改变它所在区域的内容,这是非法的 2。 赋值可能不行,类型不匹配,2维指针不确定2维数组有多少列,间接地说一下,指针+1这样的运算,不知道要加多少便宜 3。 数组里面的就不是常量字符串了,它将字符串拷贝了一份存在自己的内存中,修改的是自己内存中的内容
更多追问追答
追问
但是为什么这样又可以修改呢?:
char *ch;
ch=(char *)malloc(20);
strcpy(ch,"abcdefg");
*(ch+1)='a';
puts(ch);
这样的话输出就是aacdefg了?何解?
追答
这次是动态分配的内存,在堆上分配,这种内存可以自由修改,我说的是只有常量不让修改
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
wuqifhb
2012-05-03 · TA获得超过142个赞
知道答主
回答量:9
采纳率:100%
帮助的人:7.8万
展开全部

第一问:

      因为“abcdefg”这个字符串存放在C语言定义内存的静态存储区,这个区的特点是程序运行时不能修改其内容,而当指针指向这个存储区时,也当然不可以修改啦。可修改内容的区有内存栈区和内存堆区,而静态生成的数组就定义在栈区,如果你的指针指向该区,当然就可以修改啦,所以你的程序写成这样:char *ch;char a[]="abcdefg";ch =a; 则可以这样修改:*(ch+1)=‘a’;这是因为栈区可以修改的啦。

第二问:

      因为你的x是指向指针的指针,这个意思是这个x是一个指针,这个指针指向的变量的存储区必须是指针类型的,而你的str[20][100]申请的二维数组时按线性排列的存储区(如下图所示),且存储的内容是char型而不是指针型,虽然str是一个指针,但是这个指针指向的是数组的第一个元素,和一维数组的指针没有太大区别,只是区别在指针加一时是按照数组列的长度来移动指针,所以该指针不是一个指向指针的指针,而是一个指向元素的指针,当让不能赋值给指向指针的指针ch啦,一般大家都是通过一个中间的指针数组来过渡的,这样写:char **x;char *a[20];char str[20][100]={}; x=a;for(i=0to20)a[i]=str[i];这是因为a数组元素存的是指针,所以数组名是一个指向指针数组的指针,当然就可以赋值给x了。但是你要注意的是指针的移动只是按照一个元素一个元素的移动,他不会随你指向的是数组元素而变成二维数组那样的移动一个行,所以在使用多级指针而不是多维数组名时要这样写:*(*(x+2*100)+3)='1';

写的手都麻了,还画了图,楼楼加分啊!

追问
*(*(x+2*100)+3)='1';这个还是不太理解,这个和这个:*(x+2*100+3)有什么不一样啊?也就是说
char *p;
char a[3][10]={"abcd","1234"};
p=a;
*(p+2*10+2)='5';
这样是用一级指针来修改字符‘2’,用2级指针怎么操作?不明白
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
nju_chenbin
2012-06-24
知道答主
回答量:1
采纳率:0%
帮助的人:1607
展开全部

你自己有没有亲自测试过?

你就确定网上说的都是真的?char *ch = “abcdefg"; *(ch+1)='a';真的不可以修改???

建议还是自己亲自动手测试一下!

附上测试代码:

#include<stdio.h>

void fun(char a[10])

{

printf("sizeof(a) = %d\n", sizeof(a));

}

int main(void)

{

char a[5] = {"abcd"};

//fun(a);

printf("a = %d\n", a);

char *p = "abcd";

*p = 'x';

printf("*p = %c\n", *p);

*(++p) = 'y';

printf("*p = %c\n", *p);

p[2] = 'z';

printf("p[2] = %c\n", p[2]);

//p[3] = '\0';

printf("*p = %s", p);

return 0;

}

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
沫沫鱼在吉林
2012-05-02
知道答主
回答量:6
采纳率:0%
帮助的人:8820
展开全部
对于第一个 ch是一个指针变量,他只能指向地址,ch="abcdefg";是将该字符串的首地址赋给ch,也即将ch指向该字符串首地址;而*操作与&互为逆运算,*ch是将ch所指向的地址内存中的数取出来----也就是说*ch是个常量,不能对其赋值。

对于第二个问题,你可以试一下x=str是不行的;这个问题我们不需深究;但你要记住,一 维数组
int *x=p是可以的,但是对于二维数组int **x=str是不可以的;那么我们可以这么理解记忆一维数组首地址是1,二维数组首地址是1.5;一级指针是1,二级指针式2;即一维数组首地址能给一级指针赋值;但二维数组不能给二级指针赋值。

x=str; 会出错;
*(*(x+2)+3)='1';同样会出错 你可以再编译器上试试。
更多追问追答
追问
但是为什么这样又可以修改呢?:
char *ch;
ch=(char *)malloc(20);
strcpy(ch,"abcdefg");
*(ch+1)='a';
puts(ch);
这样的话输出就是aacdefg了?何解?
追答
(1)char *ch;   定义了一个char型的指针;
(2)h=(char *)malloc(20); 动态分配了一个字节的内存,并把该内存的首地址赋给了ch;
(3)trcpy(ch,"abcdefg");将指针ch指向字符串首地址,注意这个用法,我们给字符数组赋值时ch位置是字符数组的首地址,即一个指针;
(4)(ch+1)='a';将ch所指内存的下一个内存赋值‘a’,当前ch指向"abcdefg"中的'a'所在内存,
那么ch+1则指向‘b’所在内存,*(ch+1)='a';操作将b所在内存值赋成‘a’,即将‘b’替换成'a';
(5)最后输出该字符串,即aacdefg
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(6)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式