C语言 char * 和 char[] 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25653034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The difference between char * and char[]
提问by AALC
I've read so many threads and questions about it and read so many answers but STILL having difficulties understanding the differences and when you should use what ?
我已经阅读了很多关于它的主题和问题并阅读了很多答案,但仍然难以理解差异以及何时应该使用什么?
I think you should use char* when you need to store data and you don't know the size of it because it's dynamic. Also I'm not sure if i'm right but from what I've understand if you declare a char* and assign it a literal text like this : char *ch = "hi"; it's a constant that you can't change and if you do try to change it you'll just point ch to another allocated memory space holding the new string ? If write it this way : char ch = malloc(20); then you can change the value and if you do this : char ch[] = "hi"; charpch = ch; you can change the values aswell because you point to the array and the arrays points to ch[0] ?
我认为当你需要存储数据并且你不知道它的大小时你应该使用 char* ,因为它是动态的。另外,我不确定我是否正确,但据我所知,如果您声明一个 char* 并为其分配一个文字文本,如下所示: char *ch = "hi"; 这是一个无法更改的常量,如果您确实尝试更改它,您只需将 ch 指向另一个已分配的存储新字符串的内存空间?如果这样写: char ch = malloc(20); 那么你可以改变这个值,如果你这样做: char ch[] = "hi"; 字符pch = ch; 您也可以更改值,因为您指向数组并且数组指向 ch[0] ?
All the is written in bold is my understanding from reading, although I'm probably wrong about most of the stuff I just said and that's why I need a REALLY GOOD and simple explanation so I could once and for all understand the differences and when I should use what.
所有以粗体写成的都是我从阅读中得到的理解,尽管我刚刚说的大部分内容我可能都错了,这就是为什么我需要一个非常好的简单解释,这样我才能一劳永逸地理解差异,当我应该用什么。
EDIT :
编辑 :
#include <stdio.h>
main()
{
char ch[] = "Hello";
char *p1 = ch;
char *p2 = p1;
char *p3 = *p1;
printf("ch : %s\n", ch);
printf("p1 address [%d] value is %s\n", p1, *p1);
printf("p2 address [%d] value is %s\n", p2, *p2);
printf("p3 address [%d] value is %s\n", p3, *p3);
return 0;
}
回答by Cloud
The most straightforward answer is:
最直接的答案是:
The difference here is that
char *s = "Hello world";will place Hello world in the read-only parts of the memory and making s a pointer to that, making any writing operation on this memory illegal. While doing:
char s[] = "Hello world";puts the literal string in read-only memory and copies the string to newly allocated memory on the stack. Thus making
s[0] = 'J';legal.
这里的区别在于
char *s = "Hello world";将 Hello world 放置在内存的只读部分,并使 sa 指针指向该部分,从而使对该内存的任何写入操作都是非法的。做的时候:
char s[] = "Hello world";将文字字符串放在只读内存中,并将字符串复制到堆栈上新分配的内存中。从而使
s[0] = 'J';合法的。
A more lengthy explanation would include what segments the memory is stored in, and how much memory is allocated:
更冗长的解释将包括内存存储在哪些段中,以及分配了多少内存:
Example: Allocation Type: Read/Write: Storage Location: Memory Used (Bytes):
===========================================================================================================
const char* str = "Stack"; Static Read-only Code segment 6 (5 chars plus '#include <stdio.h>
int main() {
char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store
* 'H', 'e', 'l', 'l', 'o', '#include <stdio.h>
int main(void) {
char c = 'H'; // A character
char* pC = &c; // A pointer to a single character; IS NOT A STRING
char cArray[] = { 'H', 'e', 'l', 'l', 'o' }; // An array of characters; IS NOT A STRING
char cString[] = { 'H', 'e', 'l', 'l', 'o', '#include <stdio.h>
int main() {
char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store
* 'H', 'e', 'l', 'l', 'o', 'ch : Hello
p1 address [0x7fff58e45666] value is Hello
p2 address [0x7fff58e45666] value is Hello
p3 address [0x7fff58e45666] value is Hello
'
*/
char *p1 = ch; /* OK; Creating a pointer that points to the
* "Hello" string.
*/
char *p2 = p1; /* OK; Creating a second pointer that also
* points to the "Hello" string.
*/
char *p3 = p1; /* OK; Assigning a pointer-to-char to a
* pointer-to-char variables.
*/
printf("ch : %s\n", ch); /* OK */
printf("p1 address [%p] value is %s\n", p1, p1); /* Fixed format specifiers */
printf("p2 address [%p] value is %s\n", p2, p2); /* Fixed format specifiers */
printf("p3 address [%p] value is %s\n", p3, p3); /* Fixed format specifiers */
return 0;
}
' }; // An array of characters with a trailing NULL charcter; THIS IS A C-STYLE STRING
// You could also replace the '##代码##' with 0 or NULL, ie:
//char cString[] = { 'H', 'e', 'l', 'l', 'o', (char)0 };
//char cString[] = { 'H', 'e', 'l', 'l', 'o', NULL };
const char* myString = "Hello world!"; // A C-style string; the '##代码##' is added automatically for you
printf("%s\n", myString); // OK; Prints a string stored in a variable
printf("%s\n", "Ducks rock!"); // OK; Prints a string LITERAL; Notice the use of DOUBLE quotes, " "
printf("%s\n", cString); // OK; Prints a string stored in a variable
printf("%c\n", c); // OK; Prints a character
printf("%c\n", *pC); // OK; Prints a character stored in the location that pC points to
printf("%c\n", 'J'); // OK; Prints a character LITERAL; Notice the use of SINGLE quotes, ' '
/* The following are wrong, and your compiler should be spitting out warnings or even not allowing the
* code to compile. They will almost certainly cause a segmentation fault. Uncomment them if you
* want to see for yourself by removing the "#if 0" and "#endif" statements.
*/
#if 0
printf("%s\n", c); // WRONG; Is attempting to print a character as a string, similar
// to what you are doing.
printf("%s\n", *pC); // WRONG; Is attempting to print a character as a string. This is
// EXACTLY what you are doing.
printf("%s\n", cArray); // WRONG; cArray is a character ARRAY, not a C-style string, which is just
// a character array with the '##代码##' character at the end; printf
// will continue printing whatever follows the end of the string (ie:
// random memory, junk, etc) until it encounters a zero stored in memory.
#endif
return 0;
}
'
*/
char *p1 = ch; /* OK; Creating a pointer that points to the
* "Hello" string.
*/
char *p2 = p1; /* OK; Creating a second pointer that also
* points to the "Hello" string.
*/
char *p3 = *p1; /* BAD; You are assigning an actual character
* (*p1) to a pointer-to-char variable (p3);
* It might be more intuitive if written in
* 2 lines:
* char* p3;
* p3 = *p1; //BAD
*/
printf("ch : %s\n", ch); /* OK */
printf("p1 address [%d] value is %s\n", p1, *p1); /* Bad format specifiers */
printf("p2 address [%d] value is %s\n", p2, *p2); /* Bad format specifiers */
printf("p3 address [%d] value is %s\n", p3, *p3); /* Bad format specifiers */
return 0;
}
')
char* str = "Stack"; Static Read-only Code segment 6 (5 chars plus '##代码##')
char* str = malloc(...); Dynamic Read-write Heap Amount passed to malloc
char str[] = "Stack"; Static Read-write Stack 6 (5 chars plus '##代码##')
char strGlobal[10] = "Global"; Static Read-write Data Segment (R/W) 10
References
参考
- What is the difference between char s[] and char *s in C?, Accessed 2014-09-03,
<https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c> - Difference between declared string and allocated string, Accessed 2014-09-03,
<https://stackoverflow.com/questions/16021454/difference-between-declared-string-and-allocated-string>
- C 中的 char s[] 和 char *s 有什么区别?, 访问时间 2014-09-03,
<https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c> - 声明字符串和分配字符串的区别,访问时间 2014-09-03,
<https://stackoverflow.com/questions/16021454/difference-between-declared-string-and-allocated-string>
Edit
编辑
To address the edit in the question and the comment issued with it, I've added notes to your solution:
为了解决问题中的编辑以及随之发表的评论,我在您的解决方案中添加了注释:
##代码##So, three major bugs.
所以,三个主要错误。
- You are assigning a
charvalue to apointer-to-charvariable. Your compiler should be warning you about this. (char *p3 = *p1). - Depending on your compiler, you may have to use the pointer
%pformat specifier to print out an address rather than the%d(integer) format specifier. - You are using the string
%sspecifier with achardata type (ie:printf("%s", 'c')is wrong). If you are printing a single character, you use the%cformat specifier, and the matching argument should be a character (ie: 'c', char b, etc). If you are printing an entire string, you use the%sformat specifier, and the argument is a pointer-to-char.
- 您正在
char为pointer-to-char变量赋值。您的编译器应该就此警告您。(char *p3 = *p1). - 根据您的编译器,您可能必须使用指针
%p格式说明符来打印地址而不是%d(整数)格式说明符。 - 您正在使用
%s具有char数据类型的字符串说明符(即:printf("%s", 'c')错误)。如果要打印单个字符,则使用%c格式说明符,并且匹配的参数应该是一个字符(即:'c'、char b 等)。如果要打印整个字符串,请使用%s格式说明符,并且参数是指向字符的指针。
Examples
例子
##代码##
Code Listing - Proposed Solution
代码清单 - 建议的解决方案
##代码##
Sample Output
样本输出
##代码##

