2011-12-27 218 views
0

我正在使用Microsoft Visual Studio环境。我遇到了一个奇怪的现象字符串分配

char *src ="123"; 
char *des ="abc"; 
printf("\nThe src string is %c", src[0]); 
printf("\tThe dest string is %c",dest[0]); 

des[0] = src[0]; 

printf("\nThe src string is %c", src[0]); 
printf("\tThe dest string is %c",dest[0]); 

结果是:

1 a 
1 a 

这意味着des[0]没有被初始化。由于src指向字符串的第一个元素。我想按规则这应该工作。

+1

请用语言标记问题,让人们知道你在说什么。 – Oded 2011-12-27 13:46:59

+0

如果你使用C++,为什么在世界上你使用'printf'和C风格的字符串? – 2011-12-27 13:50:16

+0

@CodyGray:对不起。我使用C语言作为平台。我编辑了标签。 – vinaygarg 2011-12-27 14:02:55

回答

1

由于SRC和DES用字符串文字进行初始化,其类型实际上应该是const char *,不char *;像这样:

const char * src ="123"; 
const char * des ="abc"; 

从来没有分配给他们任何一个的内存,他们只是指向预定义的常量。因此,声明des[0] = src[0]是未定义的行为;你试图在那里改变一个常数!

任何像样的编译器实际上应该警告你从const char *char *隐式转换...

如果使用C++,可以考虑使用std::string代替char *,并std::cout而不是printf

3

这是未定义的行为:

des[0] = src[0]; 

试试这个:

char des[] ="abc"; 
+0

谢谢。是的,它确实有效。但是,在这两种情况下,des都会指向同一个位置。最终'des [0]'相当于'*(des + 0)'。由未定义的行为,你指的是C规格? – vinaygarg 2011-12-27 13:54:32

+0

@vinaygarg这不是一回事。是的,我正在谈论C标准,但我希望C++标准在这方面相似。 – cnicutar 2011-12-27 13:55:51

1

科的ISO/IEC 14882 2.13.4(编程语言 - C++)表示:

  1. 字符串文字是由双引号所包围,任选的字符序列(如在2.13.2中定义的)以字母L开头,如“...”或L“...”。不以L开头的字符串文字是普通的字符串文字,也被称为窄字符串文字。一个普通的字符串文字的类型为“n常量字符数组”和静态存储持续时间(3.7),其中n是下面定义的字符串大小,并用给定字符初始化。 ...

  2. 是否所有字符串文字都是不同的(即,存储在非重叠对象中)是实现定义的。试图修改字符串文字的效果是undefined

0

vinaygarg:这意味着des[0]未被初始化。由于src指向字符串的第一个元素。我想按规则这应该工作。

首先,你必须记住* src和* dst被定义为指针,没有什么更多,没有什么更少的了。

所以你必须问自己究竟是什么“123”和“abc”以及为什么它不能被改变?长话短说,它存储在应用程序内存中,它是read-only。为什么?字符串必须与程序一起存储以便在运行时可用于您的代码,理论上讲,您应该得到一个编译器警告,将非const char*分配给const char *。为什么它是read-only? exe和dll的内存需要被保护以免被覆盖,所以它必须是只读的,以防止错误和病毒修改执行代码。

那么如何将这个字符串转换为可修改的内存呢?

// Copying into an array. 
const size_t BUFFER_SIZE = 256; 
char buffer[BUFFER_SIZE]; 
strcpy(buffer, "abc"); 
strncpy(buffer, "abc", BUFFER_SIZE-1); 
+0

@pmg我的歉意,在撰写本文时并未意识到C-only的要求。更新,谢谢指出。 – 2011-12-27 14:09:44

1

在C中,字符串文字如"123"存储为的char阵列(const char在C++)。这些数组存储在内存中,以便它们在程序的整个生命周期中都可用。尝试修改字符串文字的内容会导致未定义的行为;有时它会“工作”,有时它不会,这取决于编译器和平台,所以最好将字符串文字视为不可写。请记住,在大多数情况下,“T”的“N元素数组”类型的表达式将被转换为类型为“指向T的指针”的表达式,其值是数组中第一个元素的位置。

因此,当你写

char *src = "123"; 
char *des = "abc"; 

表达式"123"和​​从“的char 3元素数组”到“指针char”转换,并且src将指向'1'"123"des将指向​​中的'a'

再次试图修改的未定义行为一个字符串结果的内容,所以,当你写

des[0] = src[0]; 

编译器是免费治疗的发言就是了任何方式,从完全无视它完全按照你期望的对任何事情进行干预。这意味着字符串文字或指向它们的指针不能用作调用的目标参数,如strcpy,strcatmemcpy等,也不应将它们用作调用的参数,如strtok