在实际编程中,使用指向数组的指针有哪些好处?

20 浏览
0 Comments

在实际编程中,使用指向数组的指针有哪些好处?

我知道这是一个非常基础的问题,但在使用一些高级语言编写了几个项目后,我刚刚开始学习一些基础的C++编程。\n基本上我有三个问题:\n

    \n

  1. 为什么要使用指针而不是普通变量?
  2. \n

  3. 何时何地应该使用指针?
  4. \n

  5. 如何在数组中使用指针?
  6. \n

0
0 Comments

指针在实际编程中的使用有什么好处?

指针允许您从多个位置引用内存中的相同空间。这意味着您可以在一个位置更新内存,并且可以从程序中的另一个位置看到更改。您还可以通过使用指针在数据结构中共享组件来节省空间。

在任何需要获取和传递特定内存位置的地址的地方都应该使用指针。您还可以使用指针来遍历数组。

数组是一块连续的内存块,已经用特定类型分配。数组的名称包含数组的起始位置的值。当您加1时,这将带您到第二个位置。这使您可以编写循环,通过递增指针来遍历数组,而不需要显式计数器来访问数组。

以下是C语言的一个例子:

char hello[] = "hello";
char *p = hello;
while (*p)
{
    *p += 1; // 将字符的值增加1
    p += 1; // 移动到下一个位置
}
printf(hello);

输出结果为 "ifmmp",因为它获取每个字符的值并将其增加1。

"because it takes the value for each character and increments it by one" 是以ASCII表示形式还是如何?

`p=0;`会重置指针吗?

0
0 Comments

在实际编程中使用指针的好处是可以在被调用函数中修改变量或对象的值。在C++中,使用引用而不是指针是一种更好的做法。尽管引用本质上是指针,但C++在一定程度上隐藏了这个事实,使得它看起来像是按值传递。这样可以方便地改变调用函数接收值的方式,而不必修改传递的语义。

下面是两个例子:

使用引用:

public void doSomething()
{
    int i = 10;
    doSomethingElse(i);  // 通过引用传递i,因为doSomethingElse()以引用接收它,
                         // 但语法使得看起来像是按值传递
}
public void doSomethingElse(int& i)  // 以引用接收i
{
    cout << i << endl;
}

使用指针:

public void doSomething()
{
    int i = 10;
    doSomethingElse(&i);
}
public void doSomethingElse(int* i)
{
    cout << *i << endl;
}

引用比指针更安全,因为不能传递空引用。

是的,使用引用的最大优势可能就是这点了。感谢指出。没有意思的双关语 🙂

你当然可以传递空引用。只是相对于传递空指针来说,传递空引用不那么容易。

同意。如果你认为不能传递空引用,那你是错的。传递悬空引用比传递空引用更容易,但最终你都可以做到。引用并不能完全阻止工程师踩到自己的坑。[在这里查看示例](http://ideone.com/YA1WmJ)。

这不是使用指针的原因,而是使用引用的原因。实际上,这也不是一个好的原因,除非真的有必要(通常情况下并没有必要)才使用非const引用参数。

0
0 Comments

指针是在无法使用其他变量时使用的,主要用于缺乏适当功能、缺少数据类型或纯粹为了性能等情况。在C语言中,当需要复杂的数据类型(如字符串)或者需要将变量“按引用”传递给函数时,就需要使用指针。指针可以指向任何东西,如链表、结构体的成员等。在处理简单数据类型(如int和char)时,数组和指针之间几乎没有什么区别。

使用指针和数组的方法并不复杂,但容易引起混淆。例如,以下两个声明非常相似:

char* a = "Hello";
char a[] = "Hello";

可以通过以下两种方式访问数组中的任何元素:

printf("Second char is: %c", a[1]);

或者:

printf("Second char is: %c", *(a+1));

在第二种方式中,由于我们告诉printf我们要打印一个字符,所以需要使用指针运算符(*)。如果没有使用指针运算符,将打印内存地址本身的字符表示。通过使用% s而不是% c,我们将要求printf打印由'a'指向的内存地址加一(在上面的示例中),而不需要在前面加上*:

printf("Second char is: %s", (a+1)); /* 错误的写法 */

但这样不仅会打印第二个字符,而且会打印直到找到空字符(\0)为止的所有下一个内存地址中的字符。这时事情开始变得危险起来。如果您意外地尝试打印的是整数类型的变量而不是char指针,则会发生什么情况?

char* a = "Hello";
int b = 120;
printf("Second char is: %s", b);

这将打印在内存地址120上找到的任何内容,并继续打印,直到找到空字符为止。虽然这种printf语句是错误和非法的,但它可能仍然可以工作,因为在许多环境中,指针实际上是int类型。如果您使用sprintf()并将这个过长的“字符数组”分配给另一个只有一定限定空间的变量,您很可能会在内存中覆盖其他内容,导致程序崩溃(如果你很幸运)。

此外,如果在声明char数组/指针时没有给它赋予字符串值,那么在给它赋值之前必须分配足够的内存空间。可以使用malloc、calloc或类似的函数来做到这一点。以下是一些示例:

char* x;
/* 为我分配6个字节的内存,并将x指向其中的第一个字节。 */
x = (char*) malloc(6);
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* 删除内存的分配(保留)。 */
/* 但是char指针x仍然指向这个内存地址! */
free(x);
/* 与malloc相同,但在分配的空间中填充了null字符! */
x = (char *) calloc(6, sizeof(x));
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* 再次删除内存的分配... */
free(x);
/* 在声明时可以设置大小 */
char xx[6];
xx[0] = 'H';
xx[1] = 'e';
xx[2] = 'l';
xx[3] = 'l';
xx[4] = 'o';
xx[5] = '\0';
printf("String \"%s\" at address: %d\n", xx, xx);

请注意,在执行了free()释放分配的内存后,仍然可以使用变量x,但是您不知道其中存储的是什么。还要注意,由于第二次内存分配没有保证在与第一次相同的空间中进行,所以两个printf()可能会给出不同的地址。

指针在实际编程中的使用有一些好处,但应该谨慎使用,因为它们容易引起错误和问题。正确地使用指针可以提供更高的性能和更灵活的编程选项。

0