我正在试着理解用户H.S在这篇文章中写的下面一行代码中使用的指针。有人能帮助我吗?
for (char **pargv = argv+1; *pargv != argv[argc]; pargv++)
整个代码:
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("ERROR: You need at least one argument.\n");
return -1;
}
for (char **pargv = argv+1; *pargv != argv[argc]; pargv++) {
/* Explaination:
* Initialization -
* char **pargv = argv+1; --> pargv pointer pointing second element of argv
* The first element of argument vector is program name
* Condition -
* *pargv != argv[argc]; --> *pargv iterate to argv array
* argv[argc] represents NULL
* So, the condition is *pargv != NULL
* This condition (*pargv != argv[argc]) is for your understanding
* If using only *pragv is also okay
* Loop iterator increment -
* pargv++
*/
printf ("Vowels in string \"%s\" : ", *pargv);
for (char *ptr = *pargv; *ptr != '\0'; ptr++) {
if (*ptr == 'a' || *ptr == 'e' || *ptr == 'i' || *ptr == 'o' || *ptr == 'u'
|| *ptr == 'A' || *ptr == 'E' || *ptr == 'I' || *ptr == 'O' || *ptr == 'U') {
printf ("%c ", *ptr);
}
}
printf ("\n");
}
return 0;
}
问题:
1.使用第一个**pargv = argv+1
中使用的两个取消引用运算符是因为argv是一个指针数组,因此必须使用指向指针(**pargv)的指针来引用它。此语句正确吗?
1.为什么必须指向argv (argv+1)
或(&argv[1])
的地址,而不是指向其中的值(*argv[1])?
在我看来,指向地址会带来地址的int数,但我知道这样的代码是正确的,那么为什么指向地址会返回里面的值呢?
我试图通过将argv+1
替换为argv[1]
来更改下面的代码段,因为在我看来,我应该指向数组内部的值,而不是指向指向指向该值的地址,但我从编译器(愚者)中得到了一个错误。
for (char **pargv = argv+1; *pargv != argv[argc]; pargv++)
2条答案
按热度按时间xdyibdwo1#
1.使用第一个
**pargv = argv+1
中使用的两个取消引用运算符是因为argv是一个指针数组,因此必须使用指向指针(**pargv)的指针来引用它。此语句正确吗?部分正确。
您引用的
**
不是两个派生运算符。它是为变量pargv
声明的类型的一部分。whole 类型是char **
,一个指向char
的指针。因为它和
argv
的类型是一样的。虽然把argv
看作一个数组并不是不合理的,但更正确的理解是它实际上是指向数组(指针的)第一个元素的指针,而不是数组本身。在C中不可能把数组作为函数参数传递--甚至没有办法表达它。1.为什么必须指向argv
(argv+1)
或(&argv[1])
的地址,而不是指向其中的值(*argv[1])?这不是 * 必须的 *。但是使用指向数组元素的指针是一种迭代数组的方法,这就是所提供的代码正在做的。并且循环的主体通过表达式
*pargv
使用指向(指针)的值。循环可以重写为:在我看来,指向地址会带来地址的int数,但我知道这样的代码是正确的,那么为什么指向地址会返回里面的值呢?
解引用一个指针可以得到它所指向的对象,不管它是什么类型的。如果被指向的对象本身就是一个指针,也包括在内。这正是所展示的代码中所发生的。
我试图通过将
argv+1
替换为argv[1]
来更改下面的代码段,因为在我看来,我应该指向数组内部的值,而不是指向指向指向该值的地址,但我从编译器(愚者)中得到了一个错误。argv+1
不等价于argv[1]
。简单的类型分析可以告诉你:如果定义了两个表达式,则它们具有不同的类型(在示例代码中分别为char **
和char *
)。在这种情况下,argv[1]
根据定义 * 等效于*((argv)+1)
*,而argv+1
等效于&argv[1]
。o75abkj42#
我可能是错的,但请允许我尝试回答你的问题。
1.注意,argv不仅仅是一个指针数组,而是一个指向指针数组的 * 指针 。指针只是指向内存中的一个地址。你的语句是正确的。一个很好的例子是,在main中,你可以用char**argv代替char argv[]的语法,这样什么都不会改变。当你声明一个数组时,在内存中为数组的开头分配地址,并根据数据类型的大小(以字节为单位)分配空间(char,int,long等)和数组的长度。为了进一步说明,当您将参数传递给main(),传递给argv[0]的第一个参数始终是调用文件的参数。例如,如果给定的代码存储在名为“myFile.cpp”的文件中,argv[0]将指向内存中的地址,其中将存储字符“myFile.cpp”的char数组(当然是以空值终止)。argv本身的值是一个指向地址的指针,该地址表示一个地址指针数组,这些地址指针指向实际保存字符值的char数组。
1.问题2的答案直接从问题1得出。你必须指向argv当前所在的位置,因为如果你只得到(argv[1])的值,它实际上会返回一个地址,即你要查找的char数组实际开始的位置!(argv + 1)将返回第一个char[]数组参数开始的地址。
回答您的最后一个问题:argv + 1引用argv,它是一个char。argv[1]访问argv的第二个元素,它是指向char数组的指针:char。编译器根据类型定义注意到这一点并返回错误。这就是为什么需要对当前实施执行(argv+1)和(&argv[1])的原因,它们是相同的。argv+1是char**,argv[1]的地址是char**类型,但argv[1]指向的值是char* 类型。
我希望这能有所帮助。我以前从来没有回答过StackOverflow上的问题。请任何人随时纠正任何错误!
编辑:请参阅Andreas Wenzel's注解,以了解数组声明和数组指针声明的说明。