指向C

时间:2015-05-10 19:36:39

标签: c string pointers

我总是想知道这两者在C

之间有什么区别
char *str;
char str[50];

我有以下代码用于从用户输入读取字符串而不是使用gets。

int read_line(char *str, int n);

int main (int *argc, char *argv[])
{
  char *str;

  read_line(str, 50);
  printf("%s", str);
  return 0;
}

int read_line(char *str, int n)
{
  int ch, i = 0;

  while((ch = getchar()) != '\n')
  {
    if(i < n)
    {
        *str++ = ch;
        i++;
    }
}
*str = '\0';

return i;
}

编译工作正常,但我尝试运行时崩溃了。 然后我将参数更改为read_line()函数,而不是char *str我使用char str[50]

当使用char *str[50]作为参数时,程序按预期运行。

有人可以解释为什么会这样吗?或者主要区别是什么 pointer to charcharacter array

3 个答案:

答案 0 :(得分:2)

数组ID或多或少像指针一样工作。

但是使用指针你总是需要手动完成3个步骤:

  • 创建指针
  • 分配内存以指向
  • 将指针初始化为指向

char str[50];完成所有这三项,而char *str;只创建一个未初始化的指针,你甚至不创建指向的缓冲区。

指针和数组ID之间的进一步区别:

  • 数组ID仅在编译时表示数组的地址,而指针在内存中存储地址,您甚至可以更改它。
  • sizeof array返回数组大小,而sizeof ptr返回存储地址所需的内存大小。

答案 1 :(得分:1)

主要区别在于后者为50个字符分配内存(str是第一个元素的指针),而前者只是声明一个指针(除了指针变量本身的内存之外没有分配内存)。

答案 2 :(得分:1)

如果您将运行这个简单的程序

,将立即看到差异
#include <stdio.h>

int main( void )
{
    char *str1;
    char str2[50];

    printf( "%zu\n", sizeof( str1 ) );
    printf( "%zu\n", sizeof( str2 ) );
}

程序输出可能看起来像

4
50

如您所见,数组str2有足够的内存来存储最多50个字符的字符串,而指针只能存储某个内存的地址。

将数组传递给代码中的函数

read_line(str2, 50);

(其中str2声明为char str2[50];),然后数组名称被隐式转换为指向其第一个元素的指针。因此,例如这些函数声明是等价的

int read_line(char *str, int n);
int read_line(char str[50], int n);

甚至喜欢

int read_line(char str[100], int n);
int read_line(char str[], int n);

并声明相同的一个函数,因为声明为array的参数被调整为指针。

因此,当您传递数组时,函数会获取指向已分配内存的数组的第一个元素的指针,因为已定义数组。

当您像在此主函数中那样传递指针时

int main (int *argc, char *argv[])
{
  char *str;

  read_line(str, 50);
  printf("%s", str);
  return 0;
}

然后它没有被初始化并且具有一些不确定的值。结果是程序行为未定义。指针应指向一些可以存储输入数据的已分配存储器。

例如,您可以通过以下方式执行此操作

int main (int *argc, char *argv[])
{
  char *str1;
  char str2[50];

  str1 = str2;

  read_line(str1, 50);
  printf("%s", str1);

  return 0;
}

int main (int *argc, char *argv[])
{
  char *str = malloc( 50 * sizeof( char ) );

  read_line(str, 50);
  printf("%s", str);

  free( str );

  return 0;
}