为什么指针可以自由地用作数组呢?我认为指针在内存操作中更强大和重要吗?有人可以向我解释指针在哪种情况下更重要吗?
这是我的代码:
char * myString ="This is my String";
while(*myString){
putchar(*myString++);
}
puts("\n");
char * myString1 ="This is my String";
int j=0;
while(myString1[j]!='\0'){
putchar(myString1[j++]);
}
Run Code Online (Sandbox Code Playgroud)
他们打印相同的结果.
为什么指针可以自由地用作数组呢?
除非它是一个sizeof或一元&(地址)运算符的操作数,否则数组表达式将转换为指针表达式...
我认为指针在内存操作中更强大和重要吗?有人可以向我解释指针在哪种情况下更重要吗?
数组与指针有不同的用例; 他们是相关的,但不能互相替代.两者都不比另一个更重要.
例如,正如Mohamed Fouad在他的回答中提到的,数组是一组连续的元素.除非指针指向数组,否则我们不能用指针存储一组元素.
作为另一个例子,其中任何一个都可以使用但指针通常更合适,请考虑如何fscanf工作.当你想要读取一个十进制数字字符序列时int,你可以写一些像int destination; fscanf(source_file, "%d\n", &destination);.该&操作(-的地址)产生一个指针destination,指针可以fscanf写入destination的方式,是一次明显的fscanf回报.
你也可以写这个int destination[1]; fscanf(source_file, "%d\n", destination);,但是后来你会指的destination[0],可能是很多次,而不是destination......你应该保持开放的门,以避免代码中不必要的混乱,因此前一种方法(int destination; ...)已成为一种习惯用法scanf(而不是基于数组的版本),因为它更干净.
有更多的例子,指针甚至没有指向对象,因此不能存储在数组中.例如,让我们考虑一下bsearch.bsearch返回a void *,并void *在其参数中使用函数指针.这些都不被认为指向特定类型的对象,实际上前者可以指向任何类型的对象或根本没有对象.因此,当bsearch无法在数组中找到一个项目时,它会返回NULL(一个指向什么都没有的指针),这是一个无法正确替换数组的用例.
函数不是对象或值,不能存储在数组中,因此数组与函数指针没有相关的类比.
他们打印相同的结果.
也许你打算写char myString1[] = "This is my String";.这就是我们声明数组的方式.你写的,char * myString1 ...表示指针声明.
表达式myString1in myString1[j]和myString1[j++]数组表达式转换为指针表达式.那有意义吗?
该array[subscript]运营商其实是一个pointer[subscript]运营商.它等同于*(array + subscript),但回想一下array表达式变成了一个pointer expression,所以写它可能更有意义*(pointer + subscript).
为了增加上面提到的函数指针,function(call)操作符实际上是一个pointer(call)操作,它以pointer[subscribt]隐式转换发生的方式与操作非常相似.尽管如此,它是可观察到的:
typedef int main_func(void); // declare a new type named main_func to point at
int main(void) {
int x[1];
int *y = x; // notice lack of ampersand, array-to-pointer conversion happens implicitly
main_func *m = main; // notice lack of ampersand, function-to-pointer conversion happens implicitly
return (*m)(); // main calls itself via pointer m (don't do this)
}
Run Code Online (Sandbox Code Playgroud)
您可能会注意到等价,现在:在第一个示例中,重复递增指针变量,而在第二个示例中,重复递增下标.除此之外,操作实际上是相同的.
如果您正在使用任何现代优化编译器(使用-O3)进行编译,那么二进制文件之间应该没有任何区别.尽量避免过早优化; 它通常是非建设性的.编写清晰的代码,然后使用您的分析器确定最重要的瓶颈所在.