何时将内存分配给char*
我有点困惑什么时候把内存分配给char*以及什么时候把它指向const字符串 是的,我知道如果我想修改字符串,我需要为它分配内存 但是,如果我不想修改我指向的字符串,只需要传递值,我应该执行以下操作吗?与使用何时将内存分配给char*,c,string,pointers,malloc,constants,C,String,Pointers,Malloc,Constants,我有点困惑什么时候把内存分配给char*以及什么时候把它指向const字符串 是的,我知道如果我想修改字符串,我需要为它分配内存 但是,如果我不想修改我指向的字符串,只需要传递值,我应该执行以下操作吗?与使用malloc分配内存相比,以下步骤有哪些缺点 char *str = NULL; str = "This is a test"; str = "Now I am pointing here"; 只要不打算修改该字符串的内容,代码中就没有问题。此外,这些字符串文本的内存将在程序的整个生命
malloc
分配内存相比,以下步骤有哪些缺点
char *str = NULL;
str = "This is a test";
str = "Now I am pointing here";
只要不打算修改该字符串的内容,代码中就没有问题。此外,这些字符串文本的内存将在程序的整个生命周期内保留。由
malloc
分配的内存是读写,因此您可以操作该内存的内容。不幸的是,在C语言中这是合法的,但任何通过指针修改字符串文字的尝试都将导致未定义的行为
说
它将正常运行,但编译器可能会发出警告,因为您指向的是一个常量字符串
注意:只有在您不修改它时,它才会正常运行。因此,不使用
malloc
的唯一缺点是您将无法修改它。如果您有一个不想修改的字符串文本,那么您所做的是可以的:
char *str = NULL;
str = "This is a test";
str = "Now I am pointing here";
这里str
指针有一个指向的内存。在第二行中,您写入该内存“这是一个测试”
,然后在第三行中,您写入该内存“现在我指向这里”
。这在C语言中是合法的
您可能会发现它有点矛盾,但您不能修改类似这样的字符串-
str[0]='X' // will give a problem.
但是,如果您希望能够修改它,请将其用作缓冲区以保存输入行等,请使用malloc
:
char *str=malloc(BUFSIZE); // BUFSIZE size what you want to allocate
free(str); // freeing memory
当您不知道编译时所需的内存量时,请使用
malloc()
。让我们使用-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
问题是编译器生成的二进制文件将字符串文本存储在内存位置。试图在上面写,你会引起一场灾难
重要的是要了解,您在这里处理的是两种不同的系统:
str
read和write是可以的。
但是,要编写正确的代码,它应该是const char*
,而不是char*
。通过以下更改,您的示例是一段有效的C:
const char *str = "some string";
str = "some other string";
(常量字符*
指向常量字符串的指针)
在这种情况下,编译器不会发出任何警告。代码执行后,您编写的内容和内存中的内容将匹配
注意:指向常量字符串的常量指针为const char*const
:
const char *const str = "foo";
int countLettersInString(char c, char const * str);
经验法则是:尽可能保持恒定
如果您需要修改字符串,请使用动态分配(malloc()或更好,一些更高级别的字符串操作函数,如libc中的strdup等),如果您不需要,请使用字符串文字。如果您知道
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
可能会更容易些,但接下来就要由您来确定是否尝试修改它了
另一方面,如果您是编写countletersinstring
函数的人,那么只需确保编译器知道您不会通过使用const
声明字符串来修改它:
const char *const str = "foo";
int countLettersInString(char c, char const * str);
这样一来,它就可以毫无疑问地接受常量和非常量字符串。使用字符串文字的一个缺点是它们有长度限制。 因此,您应该记住文件ISO/IEC:9899 (强调矿山) 5.2.4.1翻译限制 1实现应能够翻译和执行至少一个程序,该程序至少包含以下各项的一个实例