当我想要为一个char *分配内存时,我有点困惑该何时将它指向一个const字符串。
是的,如果我希望修改字符串,我需要为其分配内存。
但是在我不希望修改所指向的字符串并且只需要传递值的情况下,我是否可以像下面这样做?与使用malloc
分配内存相比,以下步骤有什么缺点?
char *str = NULL;
str = "This is a test";
str = "Now I am pointing here";
让我们再尝试一下您的示例,使用-Wwrite-strings
编译器警告标志,您将会看到一个警告:
warning: initialization discards 'const' qualifier from pointer target type
const char *
,而不是char *
。因此,当您将文字地址分配给指针时,会丢失常量信息。-Wwrite-strings
。char *str = "foo";
str[0] = 'a';
Process terminating with default action of signal 11 (SIGSEGV)
Bad permissions for mapped region at address 0x4005E4
重要的是要理解,你正在处理两个不同的系统:
C类型系统用于帮助你编写正确的代码,并且可以很容易地进行“静音”(通过强制转换等)
内核内存页面权限用于保护您的系统,并且必须始终受到尊重。
同样,由于历史原因,这是1和2不一致的一个点。更明确地说,1比2宽松得多(导致内核终止了您的程序)。
所以不要被编译器欺骗,你声明的字符串字面量是真正的常量,你无法改变它!
考虑到您的指针str
的读写是正确的。但是,为了编写正确的代码,应该使用const char *
而不是char *
。通过以下更改,您的示例将成为有效的C代码:
const char *str = "some string";
str = "some other string";
(const char *
指向一个常量字符串的指针)
在这种情况下,编译器不会发出任何警告。一旦代码执行后,你所写的内容和内存中的内容将匹配。
注意:指向常量字符串的常量指针为const char *const
:
const char *const str = "foo";
str
将始终是只读的,为什么不将其声明为只读?char const * str = NULL;
/* OR */
const char * str = NULL;
其实,有一个原因可能会让这个过程变得困难 - 当你将字符串传递给一个没有声明自己为只读函数的函数时。假设你正在使用一个声明了这个函数的外部库:
int countLettersInString(char c, char * str);
/* returns the number of times `c` occurs in `str`, or -1 if `str` is NULL. */
这个函数有很好的文档说明,你知道它不会尝试更改字符串str
- 但是如果你用一个常量字符串调用它,你的编译器可能会给你一个警告!你知道这样做没有什么危险,但是你的编译器并不知道。
为什么?因为就编译器而言,也许这个函数确实尝试修改字符串的内容,这会导致程序崩溃。也许你非常依赖这个库,并且有许多函数都像这样行事。那么也许最好在第一次声明字符串时不要将其声明为const
,但是接下来你需要确保不要尝试修改它。
另一方面,如果你是编写countLettersInString
函数的人,则只需通过使用const
声明来确保编译器知道你不会修改字符串:
int countLettersInString(char c, char const * str);
这样它将能够无障碍地接受常量和非常量字符串。
如果您有一个不想修改的字符串字面量,那么您正在做的是正确的:
char *str = NULL;
str = "This is a test";
str = "Now I am pointing here";
在这里,指针str
指向一块内存。在第二行,您将"This is a test"
写入该内存中,然后在第三行再次写入"Now I am pointing here"
。这在C语言中是合法的。请注意,保留了HTML标签。
您可能会觉得有些矛盾,但是您无法修改以下形式的字符串:
str[0]='X' // will give a problem.
然而,如果你想修改它,或者将其用作缓冲区来保存输入行等,那么请使用malloc
:
char *str=malloc(BUFSIZE); // BUFSIZE size what you want to allocate
free(str); // freeing memory
在编译时不知道需要多少内存的情况下,请使用malloc()
。
malloc()
错误? - mucahoexit(EXIT_FAILURE)
退出应用程序吗?这是我无法想象的事情。你是否遇到过 malloc
失败的情况? - mucaho很不幸,在C语言中这是合法的,但是任何试图通过指针修改字符串字面量的尝试都会导致未定义行为。
比如说
str[0] = 'Y'; //No compiler error, undefined behavior
-Wextra
和-Wall
,否则我会找到你并杀了你。 - Alec Teal