简体   繁体   English

在ANSI C中使用指针替换字符

[英]Replacing a character using pointer in ANSI C

I am using ubuntu 12.04lts with gcc(Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3. 我正在使用gcc(Ubuntu / Linaro 4.6.3-1ubuntu5)4.6.3的ubuntu 12.04lts。 I can replace a character in a 1st program, but why can't i get output in 2nd program, even it is compiled successfully?. 我可以在第一个程序中替换字符,但是即使编译成功也不能在第二个程序中得到输出? I get segmentation fault. 我遇到细分错误。 Can anyone explain the reason? 谁能解释原因?

  #include<stdio.h>
  int main(void)
  {
  char word[] = "Bhilip";
  char *cp = word ;
  puts(word);
  cp[1] = 'T';  // allowed??
  puts(word);
  return 0;
  }



  #include<stdio.h>
  int main(void)
  {
    char * p1 = "Bhilip";
    p1[0] = 'T';    //allowed?
    printf("\nThilip");
    printf(" %s \n\n", "Thilip");
    return 0 ;
  }
char * p1 = "Bhilip";

declares a pointer to a string literal. 声明一个指向字符串文字的指针。 This may be held in read only memory so cannot be modified. 它可能保存在只读存储器中,因此无法修改。

p1[0] = 'T';

tries to modify the first character in the string literal. 尝试修改字符串文字中的第一个字符。 This results in undefined behaviour, including possibly a segfault. 这导致不确定的行为,可能包括段错误。

If you want a writeable string, you can declare a stack buffer and initialise it with a string literal 如果您想要一个可写的字符串,则可以声明一个堆栈缓冲区,并使用字符串文字对其进行初始化。

char p1[] = "Bhilip";
p1[0] = 'T'; // now allowed

As per ISO C11 6.4.5 String literals /6 (though this behaviour has been around for quite a while in earlier iterations of the standard): 根据ISO C11 6.4.5 String literals /6 (尽管此行为在标准的较早版本中已经存在了一段时间):

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. 如果程序尝试修改这样的数组,则行为是不确定的。

That means you are not permitted to modify the contents of string literals if you want the behaviour to be well defined. 这意味着如果您希望行为得到良好的定义,则不允许修改字符串文字的内容。 It may work on certain implementations but it's in no way guaranteed. 可能适用于某些实现,但绝不能保证。 In some implementations, string literals are placed into memory that is marked read-only so that attempting to modify it causes a fault to be raised. 在某些实现中,字符串文字被放置在标记为只读的内存中,因此尝试对其进行修改会引发错误。 In others (such as embedded systems), it may be placed in actual read-only memory (ROM) so that, even if it doesn't fault, the memory remains unchanged. 在其他系统(例如嵌入式系统)中,可以将其放置在实际的只读存储器(ROM)中,这样即使它没有故障,该存储器也不会更改。

One likely reason behind this is that it gives the compiler the ability to fold string literals together for efficiency. 其背后的一个可能原因是,它使编译器能够将字符串文字折叠在一起以提高效率。 For example, if your code has the two strings defined and undefined , they may exist in memory as: 例如,如果您的代码具有definedundefined的两个字符串,则它们可能以下列形式存在于内存中:

        +---+---+---+---+---+---+---+---+---+----+
0x1234: | u | n | d | e | f | i | n | e | d | \0 |
        +---+---+---+---+---+---+---+---+---+----+

with the address of undefined as 0x1234 and the address of defined as 0x1236 . 地址undefined0x1234 ,地址defined0x1236

The reason that this works: 之所以说工作:

char word[] = "Bhilip";

is because it creates an array of characters that is legally modifiable, effectively: 是因为它创建法律上可修改的,有效字符数组:

  • creating the modifiable array; 创建可修改的数组; then 然后
  • copying the individual characters into it. 将单个字符复制到其中。

In other words, it's functionally equivalent to: 换句话说,它在功能上等同于:

char word[7];             // modifiable
strcpy (word, "Bhilip");  // initialise

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM