免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4644 | 回复: 11

关于C语言字符复制的问题 [复制链接]

论坛徽章:
0
发表于 2009-04-09 10:02 |显示全部楼层
有如下程序:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <assert.h>
int main()
{
void str_cpy();
char * a = "abcde";
char * b = "fghijk";
str_cpy(a,b);
printf("%s",b);
return 1;
}

void str_cpy(char * a,char * b)
{
assert((a!=NULL)&&(b!=NULL));
while((*b++=*a++)!='\0')
NULL;
}
编译没有问题,在LINUX下执行总是报Segmentaton fault错误.请大家帮忙排下什么原因.
研究了好久.另外请大家给个不用函数来执行的程序.谢谢.

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
发表于 2009-04-09 10:22 |显示全部楼层
学学调试器,例如 gdb 的用法

论坛徽章:
0
发表于 2009-04-09 10:44 |显示全部楼层

常识错误

按 while((*b++=*a++)!='\0') 这个的写法,是将a拷贝到b
但 b是 const的 ,根本不能 改变,

改为这样可以
char  b[] = "fghijk";

但要注意溢出问题....

论坛徽章:
0
发表于 2009-04-09 12:36 |显示全部楼层
类似"abcde"这样的字符串常量, 其类型应该是const char*(因为这些内存区间的属性是只读的. 你可以想象一下, 如果它们不是只读会发生什么事情).
而将const char*赋值给char*是非法的(前者是只读, 后者是可写), 比如下面两个语句:
char * a = "abcde";
char * b = "fghijk";

但是有这样编码恶习的程序员太多了, 以致于很多编译器都妥协了, 这样的赋值不报error, 甚至不报warning. 但是这样的赋值的确是不对的, 是有很大隐患的.

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
发表于 2009-04-09 13:44 |显示全部楼层
原帖由 kouu 于 2009-4-9 12:36 发表
类似"abcde"这样的字符串常量, 其类型应该是const char*(因为这些内存区间的属性是只读的.

这个只读不只读的是实现相关的,标准又没有规定(如果我没记错的话)。

而将const char*赋值给char*是非法的(前者是只读, 后者是可写),

这种赋值在 gcc 中是有警告的。
比如下面两个语句:
char * a = "abcde";
char * b = "fghijk";

这是初始化,不是赋值。

但是这样的赋值的确是不对的, 是有很大隐患的.

有什么隐患?程序意外终止?

[ 本帖最后由 MMMIX 于 2009-4-9 13:48 编辑 ]

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
发表于 2009-04-09 16:16 |显示全部楼层
The GNU C Library:
String literals appear in C program source as strings of characters between double-quote characters (`"') where the initial double-quote character is immediately preceded by a capital `L' (ell) character (as in L"foo"). In ISO C, string literals can also be formed by string concatenation: "a" "b" is the same as "ab". For wide character strings one can either use L"a" L"b" or L"a" "b". Modification of string literals is not allowed by the GNU C compiler, because literals are placed in read-only storage.
Character arrays that are declared const cannot be modified either. It's generally good style to declare non-modifiable string pointers to be of type const char *, since this often allows the C compiler to detect accidental modifications as well as providing some amount of documentation about what your program intends to do with the string.


K&R:
There is an important difference between these definitions:
   char amessage[] = "now is the time"; /* an array */
   char *pmessage = "now is the time"; /* a pointer */
amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.


Visual C++ Language Reference:
char *szStr = "1234";
szStr[2] = 'A';      // Results undefined
Microsoft Specific:
In some cases, identical string literals can be "pooled" to save space in the executable file. In string-literal pooling, the compiler causes all references to a particular string literal to point to the same location in memory, instead of having each reference point to a separate instance of the string literal. /GF enables string pooling.


ISO_IEC 9899_1999:
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

由此看出,不管实现如何,修改字符串常量的结果都是undefined

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
发表于 2009-04-09 16:31 |显示全部楼层
原帖由 timespace 于 2009-4-9 16:16 发表
不管实现如何,修改字符串常量的结果都是undefined

没错,正因为是 undefined,编译器才有发挥的空间。GCC 有个选项, -fwritable-strings,可以把字符串常量设为可写的,虽然这个选项已经是 deprecated。

论坛徽章:
0
发表于 2009-04-09 16:35 |显示全部楼层
这两个指针指向的字符串是只读的
不能被改变

论坛徽章:
0
发表于 2009-04-10 21:04 |显示全部楼层
原帖由 kouu 于 2009-4-9 12:36 发表
类似"abcde"这样的字符串常量, 其类型应该是const char*(因为这些内存区间的属性是只读的. 你可以想象一下, 如果它们不是只读会发生什么事情).
而将const char*赋值给char*是非法的(前者是只读, 后者是可写),  ...



关键是看你怎么写代码了!
你来个int a[10];
你非要取a[11]也不行啊!呵呵!

自己多注意就好了!呵呵

论坛徽章:
1
寅虎
日期:2014-11-30 21:25:54
发表于 2009-04-16 01:27 |显示全部楼层
原帖由 kouu 于 2009-4-9 12:36 发表
类似"abcde"这样的字符串常量, 其类型应该是const char*(因为这些内存区间的属性是只读的. 你可以想象一下, 如果它们不是只读会发生什么事情).
而将const char*赋值给char*是非法的(前者是只读, 后者是可写),  ...


和const没有关系 哎这个问题 c/c++版里也有
const的变量也是可以改的 比如
const int a = 0;
*(int *)&a = 1;

char *p = "abc";
实际上"abc"是编译时放在了 .rodata 里 所以才不能改
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP