【问题标题】:About pointers and strcpy() in C关于 C 中的指针和 strcpy()
【发布时间】:2015-09-16 06:48:03
【问题描述】:

我正在练习使用带有指针的malloc() 分配内存,但是关于指针的一个观察是,为什么strcpy() 可以接受str 没有* 的变量:

char *str;
str = (char *) malloc(15);
strcpy(str, "Hello");
printf("String = %s,  Address = %u\n", str, str);

但是对于整数,我们需要 * 给 str 一个值。

int *str;
str = (int *) malloc(15);
*str = 10;
printf("Int = %d,  Address = %u\n", *str, str);

这真的让我很困惑为什么strcpy() 接受str,因为在我自己的理解中,"Hello" 将被传递到str 的内存位置,这会导致一些错误。

【问题讨论】:

  • 去掉 malloc 中的指针。见link
  • 为什么?其实这两个程序都运行的很好,就是不明白为什么strcpy可以带这样的参数
  • 使用%p 打印一个指针。 malloc(15) for int * str 也可以在以后产生问题。
  • 好的,我试图摆脱强制转换并且效果相同,但我的问题是为什么 strcpy 接受 str 是一个包含内存地址的变量?
  • @SouravKanta 除非您没有 C99 支持,如在 MSVC 中(强制转换使代码更具可移植性)。

标签: c string pointers char strcpy


【解决方案1】:

* 称为间接或取消引用运算符。

在您的第二个代码中,

 *str = 10;

10 分配给str 指向的内存地址。这是一个值(即单个变量)。

OTOTH,strcpy() 一次复制整个字符串。它接受两个char * 参数,因此您不需要* 取消引用以在传递参数时获取值。

你可以使用解引用操作符,不用strcpy(),逐个元素复制,比如

char *str;
str = (char *) malloc(15);   //success check TODO
int len = strlen("Hello");    //need string.h header

for (i = 0; i < len; i ++)
    *(str+i)= "Hello"[i];  // the * form. as you wanted

str[i] = 0;   //null termination

【讨论】:

    【解决方案2】:

    许多字符串操作函数,包括strcpy,按照惯例和设计,接受指向数组第一个字符的指针,而不是指向整个数组的指针,即使它们的是一样。

    这是因为它们的类型不同;例如指向char[10] 的指针与指向char[15] 的指针具有不同的类型,因此将指针传递给整个数组是不可能的或非常笨拙的,除非你将它们投射到任何地方或为不同的函数创建不同的函数长度。

    出于这个原因,他们已经建立了一个约定,即使用指向其第一个字符的指针而不是整个数组来传递字符串,必要时可能还带有它的长度。许多对数组进行操作的函数,例如memset,都以相同的方式工作。

    【讨论】:

      【解决方案3】:

      在 C 中,字符串(根据定义)是一个字符数组。然而(无论我们是否一直意识到)我们几乎总是最终使用指针访问数组。因此,尽管 C 没有真正的“字符串”类型,但对于大多数实际目的而言,指向字符的类型(即 char *)服务于这个目的。几乎所有接受或返回字符串的函数实际上都会使用char *。这就是strlen()strcpy() 接受char * 的原因。这就是为什么printf %s 需要char *。在所有这些情况下,这些函数需要的是指向字符串第一个字符的指针。 (然后他们依次读取字符串的其余部分,当他们找到终止的 '\0' 字符时停止。)

      在这些情况下,您不要使用明确的* 字符。 * 将只提取指向的字符(即字符串的第一个字符),但您不想提取第一个字符,您想将整个字符串(即指向整个字符串的指针) string) 到strcpy,这样它就可以完成它的工作了。

      在您的第二个示例中,您根本没有使用字符串。 (您使用了一个名为 str 的变量这一事实让我感到困惑。)您有一个指向某些 int 的指针,并且您正在使用指向的第一个 int。由于您直接访问指向的内容之一,因此您确实需要明确的 * 字符。

      【讨论】:

        【解决方案4】:

        好吧,这是第一个 sn-p 中发生的事情:

        您首先动态分配 15 个字节的内存,将此地址存储到 char 指针,它是指向 1 字节数据序列(字符串)的指针。 然后调用strcpy(),它遍历字符串并将字符逐字节复制到新分配的内存空间中。每个字符都是基于 ASCII 表的数字,例如。字符 a = 97(看看man ascii)。

        然后你将这个地址传递给printf(),它从字符串中读取一个字节一个字节,然后将它刷新到你的终端。

        在第二个sn-p中,过程是一样的,你仍然分配15个字节,将地址存储在一个int *指针中。 int 是一个 4 字节的数据类型。 当您执行*str = 10 时,您正在取消引用指针以将值 10 存储在 str 指向的地址。提醒我前面写的内容,你可以做 *str = 'a',这个索引为 0 的整数的值是 97,即使你尝试将它读为 int。如果愿意,您可以将其打印出来。

        那么为什么strcpy() 可以将int * 作为参数呢?因为它是一个可以写入的内存空间,一个字节一个字节。您可以将“Hell”存储在 int 中,然后存储“o!”在下一个。

        一切都是为了易于使用。

        【讨论】:

          【解决方案5】:

          查看= 运算符和函数strcpy 之间的区别。

          * 是遵从运算符。当你说*str时,它的意思是str指向的内存位置的值。

          也是一个好习惯,使用这个

          str = (char *) malloc( sizeof(char)*15 )
          

          这是因为不同平台上数据类型的大小可能不同。因此使用sizeof 函数来确定它在运行时的实际大小。

          【讨论】:

            猜你喜欢
            • 2017-03-30
            • 1970-01-01
            • 1970-01-01
            • 2016-03-16
            • 2017-05-13
            • 1970-01-01
            • 1970-01-01
            • 2011-12-05
            • 1970-01-01
            相关资源
            最近更新 更多