关于 C 中的指针和 strcpy()

About pointers and strcpy() in C

我正在练习使用 malloc() 和指针分配内存,但是关于指针的 1 个观察是,为什么 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的内存位置,这会导致一些错误。

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

在你的第二个代码中,

 *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

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

这是因为他们的类型不同;例如指向 char[10] 的指针与指向 char[15] 的指针具有不同的类型,因此将指针传递到整个数组是不可能的或非常笨拙的,除非您将它们到处投射或使不同长度的不同功能。

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

在 C 中,字符串(根据定义)是一个字符数组。然而(无论我们是否一直意识到这一点)我们几乎总是以使用指针访问数组而告终。因此,尽管 C 没有真正的 "string" 类型,但出于大多数实际目的,指向字符的指针类型(即 char *)可用于此目的。几乎所有接受或 returns 字符串的函数实际上都会使用 char *。这就是 strlen()strcpy() 接受 char * 的原因。这就是 printf %s 期望 char * 的原因。在所有这些情况下,这些函数需要的是指向字符串第一个字符的指针。 (然后他们依次读取字符串的其余部分,在找到终止字符 '[=17=]' 时停止。)

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

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

嗯,这是第一个片段中发生的事情:

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

然后将此地址传递给 printf(),它从字符串中逐字节读取,然后将其刷新到您的终端。

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

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

一切都是为了使用方便。

看到 = 运算符和函数 strcpy 之间存在差异。

* 是顺从运算符。当你说 *str 时,它表示 str.

指向的内存位置的值

作为一个好习惯,使用这个

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

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