我已经学习C大约2个月了,但仍然是新手:(
我知道此网站上还有其他类似的问题。我读过它们,但仍然听不懂,所以我在这里。下面是我的代码:
List<String> names= new ArrayList<String>();
names.add("John");
names.add("Mark");
if (names.stream().distinct().limit(2).count() > 1) {
a= 1,
Assert.fail("Received different name in between");
} else {
System.out.println("Received Same name");
}
和下面是我的函数接收数组:
//naming my structure as ball
typedef struct ball_room {
int enter;
int exit;
} ball;
//I've omitted some irrelevant details for brevity
int i, n, max;
scanf("%d", &n);
ball person[n];
.../*assign values to ball.enter and ball.exit with user input*/
max = 1;
for (i = 0; i < n; i++)
if (ball_room(person, person[i].enter, n) > max)
max = ball_room(person, person[i].enter, n);
printf("%d\n", max);
return 0;
}
我的问题是,为什么编译器不接受//This function returns the number of people in the ballroom
//when b[j](person[j] in "main") enters
int ball_room(ball *b, int i, int n)
{
int people = 0, j;
for (j = 0; j < n; j++)
if (b[j].enter <= i && b[j].exit > i)
people++;
return people;
}
而不是b[j].enter
?
以我有限的经验,在操纵结构本身(对象)时,我使用b[j]->enter
进入结构内部,而当它是指针(地址)时,我使用.
(希望这是正确的。 )
在这种情况下,我使用->
(代表ball *b
的地址)将数组传递给函数,因此可以访问整个数组。但是person[0]
是否不应该采用指针形式,因此我应该使用ball *b
来访问其内容?这只是我传递给函数的地址。
这是我第一次使用一系列结构进行操作,请帮助我弄清楚这一点,谢谢!
答案 0 :(得分:5)
由于使用了以下参数声明,因此您使用.
而不是->
:
int ball_room(ball *b, int i, int n)
b
应该指向类型为ball
的数据的指针,因此您可以通过多种方式访问它:
b[5].somefield = 15
-在这里使用点,因为如果b
是ball *
类型,则意味着b
是指针,或者它是类型为b
的对象数组,如果它是类型为b
的对象数组(您的情况),则可以使用.
访问对象的字段(b+5)->somefield = 15
-与上述代码完全相同,但是您将以pointer
的方式访问数据
答案 1 :(得分:5)
给出ball *b
,b[j]
是b
指向的元素中的一个元素。因此b[j]
不是指针;这是一个结构。由于它是一个结构,因此您可以使用.
来引用其中的成员。
C标准中b[j]
的定义是*((b)+(j))
。因此它需要使用指针b
,将j
元素移到其后,然后再应用*
。
由于*
中已经应用了b[j]
,因此您不需要->
,只需要.
。
答案 2 :(得分:2)
在C / C ++中,数组归入其第一个成员的地址。因此,当您将数组传递给ball_room
时,实际上传递的是&ball[0]
。
现在在ball_room
内部,情况相反。 b
是指向球的指针。但是在这里,您将其用作数组b[j]
。因此,它分解为一系列结构。因此b[j]
给您的是结构,而不是结构的指针。因此,您使用.
而不是->
来访问它。
您也可以使用(b + j)->somefield
。或者,更有趣的是如何编写j[b].somefield
。后来是以前的编译器时代留下的一个令人困惑的遗留物,当时a[b]
在内部真正变成了*(a + b)
。
答案 3 :(得分:1)
有关当前问题的说明,请参见Eric的answer;在到目前为止给出的一些答案中,使用了危险的措词,因此请明确:我们何时有数组,何时有指针??
请考虑以下内容:
int a[7];
只要我们可以直接引用a
,我们仍然有一个数组,并且可以使用在e上有效的任何操作。 G。变大:
size_t n = sizeof(a); // size in bytes, not ints, i. e. 7*sizeof(int)
您可以将数组传递给函数,甚至可以对以下各项进行指针算术:
f(a);
a + 1;
在这两种情况下,数组都“衰减”到一个指针,并且结果也是一个指针。请注意,您可以将新值分配给指针,但不能分配给数组本身(可以直接或通过指针将新值分配给数组的元素),因此也无法执行类似++a
的操作。>
当数组衰减为指针时,它将获得指向其第一个元素的指针:
int* ptr = a;
int* ptr = &*a; // only pointers can be dereferenced -> a decays!
int* ptr = &a[0]; // short for &*(a + 0)...
所有结果完全相同;但是,以下内容无效:
int* ptr = &a;
实际上可以获取整个数组的地址 ,但是结果指针既不是“指向元素的指针”类型,也不是“指向元素的指针”类型(int**
在示例中),但类型为“指向特定大小的数组的指针”。尽管的语法很丑陋,但以下内容再次合法:
int(*aptr)[7] = &a;
您需要阅读:如果我取消引用ptr
,我会得到int[7]
...
一旦衰减,仅剩下一个指向数组的指针(更精确的是:衰减后直接指向数组元素中的一个,指向第一个;数组和第一个元素始终共享相同的地址,因此,尽管类型不同,上面的两个指针ptr
和aptr
的值完全相同)。指针可以在数组内移动,但是指针所保存的信息不如数组本身,尤其是数组大小会丢失。这就是为什么需要将数组的长度与指向函数的指针一起传递的原因(如果需要;另一种变体是表示数组末尾的前哨值,例如字符串中的终止空字符或{{1 }}的参数列表):
main
可能将f设置为:
int a[7];
f(a, sizeof(a));
希望这有助于避免混乱。
答案 4 :(得分:0)
在C语言中,数组名称是指向数组第一个元素的指针,因此您的函数声明的名称为ball *b
,并在您传递ball[]
实例时起作用。
尝试使用malloc()
动态分配内存并将该指针传递给函数。