一直在想,用[]或*声明变量之间的区别是什么?我看待它的方式:
char *str = new char[100];
char str2[] = "Hi world!";
..应该是主要区别,但我不确定你是否可以做类似
的事情char *str = "Hi all";
..因为指针应该引用一个静态成员,我不知道它是否可以?
无论如何,真正困扰我的是知道它们之间的区别:
void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};
那么,如果有人能告诉我差异,我们将不胜感激吗?我有一种预感,除了在某些特殊情况下,两者都可以编译得相同吗?
泰
答案 0 :(得分:41)
让我们看看它(对于以下内容,注意char const
和const char
在C ++中是相同的):
"hello"
是一个包含6个const字符的数组:char const[6]
。作为每个数组,它可以隐式转换为指向其第一个元素的指针:char const * s = "hello";
为了与C代码兼容,C ++允许另外一个转换,否则会形成错误:char * s = "hello";
它会删除const !这是一个例外,允许编译C-ish代码,但不推荐使用char *
指向字符串文字。那么我们对char * s = "foo";
有什么看法?
"foo"
- > array-to-pointer
- > char const*
- > qualification-conversion
- > char *
。字符串文字是只读的,不会在堆栈上分配。您可以自由地使指针指向它们,并从函数返回该指针,而不会崩溃:)。
现在,char s[] = "hello";
是什么?这是整个其他的东西。这将创建一个字符数组,并用字符串"hello"
填充它。字面意思没有指出。而是将其复制到字符数组中。并且数组在堆栈上创建。您无法从函数中有效地返回指向它的指针。
如何使函数接受数组作为参数?您只需将参数声明为数组:
void accept_array(char foo[]);
但是你省略了它的大小。实际上,任何大小都会这样做,因为它只是被忽略:标准说,以这种方式声明的参数将被转换为与
相同void accept_array(char * foo);
以任何类型替换char
,包括数组本身:
void accept_array(char foo[][10]);
接受一个二维数组,其最后一个维度的大小为10. 多维数组的第一个元素是它的下一个维度的第一个子数组!现在,让我们改变它。它将再次指向其第一个元素。所以,实际上它会接受一个指向10个字符数组的指针:(删除头部的[]
,然后只需指向你在脑中看到的类型的指针):
void accept_array(char (*foo)[10]);
当数组隐式转换为指向其第一个元素的指针时,您只需在其中传递一个二维数组(其最后一个维度大小为10),它就可以工作。实际上,任何 n维数组都是这种情况,包括n = 1
的特殊情况;
void upperCaseString(char *_str) {};
和
void upperCaseString(char _str[]) {};
是相同的,因为第一个只是一个指向char的指针。但请注意,如果您想将String-literal传递给它(假设它不会更改其参数),那么您应该将参数更改为char const* _str
,这样您就不会弃用。
答案 1 :(得分:12)
三个不同的声明使指针指向不同的内存段:
char* str = new char[100];
让str指向堆。
char str2[] = "Hi world!";
将字符串放在堆栈上。
char* str3 = "Hi world!";
指向数据段。
两个声明
void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};
是相同的,当你尝试在同一范围内声明它们时,编译器会抱怨已经有一个正文的函数。
答案 2 :(得分:2)
好的,我留下了两条负面评论。这不是很有用;我删除了它们。
char *str = new char[100];
可以使用delete []
释放此块。
char [] str2 = "Hi world!";
这个数组可以毫无问题地修改,这很好。所以
str2[0] = 'N';
cout << str2;
应该将Ni world!
打印到标准输出,让某些骑士感到非常不舒服。
char *str = "Hi all";
str[0] = 'N'; // ERROR!
void upperCaseString(char *_str) {};
void upperCaseString(char [] _str) {};
对我来说看起来与相同,在你的情况下(你想要将字符串大写到位),这无关紧要。
然而,所有这些都引出了一个问题:为什么使用char *
在C ++中表达字符串?
答案 3 :(得分:0)
作为已经给出的答案的补充,您应该阅读the C FAQ regarding arrays vs. pointers。是的,这是一个C FAQ而不是C ++常见问题解答,但这个领域的两种语言之间几乎没有实质性区别。
另外,作为旁注,请避免使用前导下划线命名变量。这是为编译器和标准库定义的符号保留的。
答案 4 :(得分:0)
请同时查看http://c-faq.com/aryptr/aryptr2.html C-FAQ本身可能是一本有趣的读物。
答案 5 :(得分:-1)
第一个选项动态分配100个字节。
第二个选项静态分配10个字节(字符串+ nul字符为9)。
您的第三个示例不起作用 - 您正在尝试静态填充动态项目。
对于upperCaseString()
问题,一旦分配并定义了C字符串,就可以通过数组索引或指针表示法迭代它,因为数组实际上只是一种方便的方法来包装指针C中的算术。
(这是一个简单的答案 - 我希望其他人会从规范中获得权威,复杂的答案:))