C中的字符串操作

时间:2012-10-05 09:28:31

标签: c string malloc literals

以下是我对C中字符串的一些基本问题。

  • 如果字符串文字存储在只读数据段中,并且在初始化后无法更改,那么以下两个初始化之间有什么区别
  
    

char * string =“Hello world”;

         

const char * string =“Hello world”;

  
  • 当我们为字符串动态分配内存时,我看到下面的分配足以容纳一个任意长度的字符串。虽然这个分配工作,但我认为,分配实际字符串的实际大小总是好的做法而不是数据类型的大小。请指导正确使用字符串的动态分配
  
    

char * str =(char *)malloc(sizeof(char));

         

的scanf( “%S”,STR);

         

的printf( “%S \ n” 个,STR);

  

7 个答案:

答案 0 :(得分:2)

1. 以下两个初始化之间有什么区别。 不同之处在于错误的编译和运行时检查,正如其他人已经告诉过的那样。

  

char * string =“Hello world”; --->存储在只读数据段中   无法更改,但如果您更改该值,则编译器不会给出   任何错误只会在运行时出现。

     

const char * string =“Hello world”; --->这也存储在读取中   只有具有编译时检查的数据段,因为它被声明为   const所以,如果你要更改字符串的值,那么你将得到一个   编译时出错,这比运行时的失败要好得多。

2. 请指导正确使用字符串的动态分配。

 char *str = (char *)malloc(sizeof(char));
 scanf("%s",str);
 printf("%s\n",str);

此代码可能会有效,但并非总是如此。问题出现在run-time,当您访问segmentation fault时,area of memory会被您的程序拥有你应该在这个dynamic memory allocation中一直非常小心,因为它会导致非常危险error at run time

你应该始终allocate the amount of memory you need correctly。 最大的错误发生在use of string期间。您应该始终牢记is a '\0' character present at last of the string,并且在分配期间your responsibility to allocate memory for this.

希望这有帮助。

答案 1 :(得分:1)

  

以下两个初始化之间有什么区别。

由于遗留原因,字符串文字的类型为char*。最好只通过const char*指向它们,因为不允许修改它们。

  

我看到以下分配足以容纳一个任意长度的字符串。

错误。此分配仅为一个字符分配内存。如果您尝试在string中写入多个字节,则会出现缓冲区溢出。

动态分配内存的正确方法很简单:

char *string = malloc(your_desired_max_length);

此处显式强制转换是多余的,sizeof(char)按定义为1。

另外:请记住,字符串终结符(0)也必须符合字符串。

答案 2 :(得分:1)

两个声明之间的区别在于,如果尝试通过const char*声明的指针修改字符串文字,编译器将产生错误(这比运行时故障更可取)。以下代码:

const char* s = "hello"; /* 's' is a pointer to 'const char'. */
*s = 'a';

导致VC2010发出以下错误:

  

错误C2166:l-value指定const对象

尝试修改通过char*声明的指针生成的字符串文字,直到运行时才会检测到(VC2010没有发出错误),其行为未定义。

malloc()内存用于存储字符串时,必须记住分配一个额外的char来存储空终止符作为所有(或几乎所有)C字符串处理函数需要null终止符。例如,要分配缓冲区以存储"hello"

char* p = malloc(6); /* 5 for "hello" and 1 for null terminator. */

sizeof(char)保证为1,因此不需要,并且无需转换malloc()的返回值。当不再需要p时,请记住free()已分配的内存:

free(p);

答案 3 :(得分:1)

在第一种情况下,您明确地将char*强制转换为const,这意味着您在编译器级别禁止对其后面的字符进行更改。在C中,实际上是未定义的行为(在运行时)尝试修改这些字符而不管它们的常量,但是字符串文字 char *,而不是const char *

在第二种情况下,我看到两个问题。

第一个是你永远不应该从malloc转换返回值,因为它可以掩盖某些错误(特别是在指针和整数大小不同的系统上)。具体来说,除非有适当的malloc原型,否则编译器可能会认为它返回int而不是正确的void *

因此,如果您忘记包含stdlib.h,您可能会遇到编译器无法警告您的一些有趣行为,因为您通过明确的演员告诉它您知道你在做什么。

C完全能够在从void *返回的malloc和任何其他指针类型之间进行隐式转换。

第二个问题是它只为一个字符分配空间,这将是一个字符串的终止空值。

最好写成:

char *string = malloc (max_str_size + 1);

(并且不要乘以sizeof(char),这是浪费时间 - 它总是 1)。

答案 4 :(得分:1)

以下两个初始化之间的差异。

  
    

首先, char * string =“Hello world”;
       - 将“Hello world”存储在堆栈段中作为常量字符串,并将其地址分配给指针的字符串'变量       “Hello world”是不变的。并且你不能做字符串[5] ='g',这样做会导致分段错误       其中'string'变量本身不是常数。你可以改变它的约束力:
      string =“其他一些字符串”; //这是正确的,没有分段错误

         

const char * string =“Hello world”;
      再次将“Hello world”存储在堆栈段中作为常量字符串,并将其地址分配给“string”变量。       并且字符串[5] ='g',这会导致分段错误       这里没有使用const关键字!

  

现在,
  char * string =(char *)malloc(sizeof(char));

  
    

以上声明与第一个相同,但这次你的分配是来自堆段(不是来自堆栈)的动态

  

答案 5 :(得分:0)

代码:

char *string = (char *)malloc(sizeof(char));

不会持有任意长度的字符串。它将分配一个字符并返回一个指向char字符的指针。请注意,指向字符的指针和指向字符串的指针是相同的。

要为字符串分配空间,您必须执行以下操作:

char *data="Hello, world";
char *copy=(char*)malloc(strlen(data)+1);
strcpy(copy,data);

您需要准确地告诉malloc要分配的字节数。 +1用于需要结束的空终止符。

对于存储在只读段中的文字字符串,这是一个实现问题,尽管几乎总是如此。大多数C编译器都非常放松地对这些字符串进行访问,但是尝试修改它们会遇到麻烦,所以你应该总是声明它们const char *以避免任何问题。

答案 6 :(得分:0)

这个特定的分配可能看起来有效,因为程序堆中可能有足够的空间,但事实并非如此。您可以通过使用建议的方法和memcpy分配两个“任意”字符串来验证它:将足够长的字符串分配给相应的地址。在最好的情况下,你会看到垃圾,在最坏的情况下,你会有分段错误或从malloc或free中断言。