关于C语言中指针和strcpy()函数

3

我正在使用指针和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的内存位置,这会导致一些错误。


1
在malloc中去掉指针转换。请参阅此链接 - Sourav Kanta
为什么?实际上这两个程序运行得很好,我只是不明白为什么strcpy可以接受这样的参数。 - Gelo
使用%p打印指针。同时,对于int * str,使用malloc(15)可能会在后面造成问题。 - Sourav Ghosh
好的,我尝试去掉强制转换,结果它仍然有效,但我的问题是为什么strcpy接受包含内存地址的变量str? - Gelo
@SouravKanta 除非你的编译器不支持C99,例如MSVC(强制转换可以使代码更具可移植性)。 - jn1kk
5个回答

4
在C语言中,字符串(按定义)是字符数组。然而(无论我们是否一直意识到这一点),我们几乎总是使用指针来访问数组。因此,虽然C语言没有真正的“字符串”类型,但对于大多数实际目的来说,指向字符的指针类型(即char *)可以起到这个作用。几乎任何接受或返回字符串的函数都会实际使用char *。这就是为什么strlen()strcpy()接受char *的原因。这就是为什么printf %s期望一个char *的原因。在所有这些情况下,这些函数需要的是指向字符串第一个字符的指针。 (然后它们按顺序读取其余的字符串,在找到终止的'\0'字符时停止。)
在这些情况下,您不使用显式的*字符。 *将只提取指向的字符(即字符串的第一个字符),但您不想提取第一个字符,而是想将整个字符串(即指向整个字符串的指针)交给strcpy以便它能够完成其工作。
在您的第二个示例中,您根本没有使用字符串。(您使用名为str的变量的事实让我有些困惑。)您有一些int指针,并且正在使用指向的第一个int。由于您直接访问了其中一个指向的内容,这就是为什么您需要显式的*字符的原因。

1
*被称为间接或解引用运算符。 在你的第二段代码中,
 *str = 10;

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

另一方面,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

0
许多字符串操作函数,包括 strcpy ,按照惯例和设计,接受指向数组第一个字符的指针,而不是整个数组的指针,尽管它们的值是相同的。
这是因为它们的类型不同;例如,指向 char[10] 的指针与指向 char[15] 的指针具有不同的类型,传递整个数组的指针将是不可能或非常笨拙的,除非您在每个地方都进行强制转换或创建不同长度的函数。
因此,他们建立了一种传递字符串的约定,其中包括指向其第一个字符的指针,可能还包括必要时的长度。许多操作数组的函数,如 memset,也采用相同的方式工作。

0

好的,下面是第一个片段发生的事情:

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

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

在第二个片段中,过程相同,您仍然分配15个字节,将地址存储在int *指针中。 int是4字节数据类型。 当您执行*str = 10时,您正在取消引用指针以将值10存储在由str指向的地址处。提醒一下我之前写的内容,您可以做* str ='a',即使您尝试将其读取为int,此索引0整数也将具有值97。如果您愿意,甚至可以打印它。

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

这只是关于使用的便捷性。


0

看起来赋值运算符=和函数strcpy之间有所不同。

*是解引用运算符。当你说*str时,它表示指针str所指向的内存位置上的值。

此外,作为良好的编程习惯,请使用这个:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接