1

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

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

char *string = "你好世界";

const char *string = "你好世界";

  • 当我们为字符串动态分配内存时,我看到以下分配足以容纳任意长度的字符串。尽管这种分配有效,但我理解/相信分配实际字符串的实际大小而不是数据类型的大小。请指导正确使用字符串的动态分配

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

scanf("%s",str);

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

4

7 回答 7

2

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

char *string = "你好世界"; --->存储在只读数据段中并且不能更改,但是如果您更改值,那么编译器不会给出任何错误,它只会在运行时出现。

const char *string = "你好世界"; --->这也存储在带有编译时检查的只读数据段中,因为它被声明为 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.You 应该始终记住,is a '\0' character present at last of the string在分配期间your responsibility to allocate memory for this.

希望这可以帮助。

于 2012-10-05T10:43:13.220 回答
1

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

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

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

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

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

char *string = malloc(your_desired_max_length);

显式转换在这里是多余的,sizeof(char)根据定义为 1。

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

于 2012-10-05T09:34:08.173 回答
1

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

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

导致VC2010发出以下错误:

错误 C2166:左值指定 const 对象

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

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

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

sizeof(char)保证为 1,因此不需要,也没有必要强制转换 的返回值malloc()。何时p不再需要记住free()分配的内存:

free(p);
于 2012-10-05T09:36:16.847 回答
1

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

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

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

因此,如果您忘记包含stdlib.h,您可能会遇到一些编译器无法警告您的有趣行为,因为您通过显式强制转换告诉它您知道自己在做什么。

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

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

最好写成:

char *string = malloc (max_str_size + 1);

(永远不要乘以sizeof(char),那是浪费时间 - 它总是1)。

于 2012-10-05T09:37:12.773 回答
1

以下两个初始化之间的区别。

首先,char *string = "Hello world";
- “Hello world”作为常量字符串存储在堆栈段中,其地址分配给指针'string'变量。
“你好世界”是不变的。而且你不能做string[5]='g',这样做会导致分段错误。
其中“字符串”变量本身不是恒定的。你可以改变它的绑定:
string= "Some other string"; //这是正确的,没有分段错误

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

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

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

于 2012-10-05T09:41:50.553 回答
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 访问这些字符串非常放松,但尝试修改它们是自找麻烦,因此您应该始终声明它们const char *以避免任何问题。

于 2012-10-05T09:33:32.190 回答
0

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

于 2012-10-05T09:35:03.443 回答