c语言 - 结构中的指针表示法和点表示法之间的混淆



我正在尝试使结构中的所有名称都小写,以便我可以比较它们并删除它们。

int removeNameCard(NameCard *idCard, int *size){
char name[80];
char *ptr;
char rubbish;
int a = 0, c = 0;
printf("removeNameCard():n");
printf("Enter personName:n");
scanf("%c", &rubbish); // Why is there a 'n' char here??
fgets(name, 80, stdin);
if((ptr = strchr(name, 'n'))){
*ptr = '';
}
if((*size) == 0){
printf("The name card holder is emptyn");
return 0;
}
// Convert everything to Lower Case first
while(name[a]){
name[a] = tolower(name[a]);
a += 1;
}
printf("tolower(): %s", name);
for(int b = 0; b < *size; b += 1){
// Why is this Dot Notation when I passed in a pointer to the Struct?
while (idCard[b].personName)[c]){
(idCard[b].personName)[c] = tolower((idCard[b].personName)[c]);
c += 1;
}
}
for(int i = 0; i < *size; i += 1){
if((idCard[i].personName) == name){
printf("%d. This is from Holder: %s, This is from User: %s", i,(idCard[i].personName),name);
printf("The name card is removedn");
printf("nameCardID: %dn", idCard[i].nameCardID);
printf("personName: %sn", idCard[i].personName);
printf("companyName: %sn", idCard[i].companyName);
int k = 0;
do{
idCard[i+k].nameCardID = idCard[i+k+1].nameCardID;
strcpy((idCard[i+k].personName),(idCard[i+k+1].personName));
strcpy((idCard[i+k].companyName),(idCard[i+k+1].companyName));
}while((i+k+1) != (*size + 1));
}
}
return 0;
}

但是,我很困惑为什么编译器要求我使用点表示法而不是指针表示法,因为我认为我将结构的地址传递到 *idCard 中,所以如果我没有错的话,它应该是一个指针?

我试图像这样访问结构的每个名称中的每个字符是错的吗? (身份证[b].人名)[三]

谢谢

但是,我很困惑为什么编译器要求我使用点表示法而不是指针表示法......

idCard[i]是一个结构,而不是指向结构的指针,因此它的成员是作为idCard[i].member而不是idCard[i]->member访问的。

idCard[i]是一个结构,因为只要x是指针,x[i]就是x指向的对象之一。它不是对象的地址。你可以用x+i计算对象的地址,然后你可以用*(x+i)引用对象。x[i]实际上是这样定义的;x[i]被定义为*(x+i)。(对于表达式,通常将E1[E2]定义为(*((E1)+(E2)))

我试图像这样访问结构的每个名称中的每个字符是错误的吗?:(idCard[b].personName)[c]

这将起作用,但括号是不必要的。您可以使用idCard[b].personName[c].由于 C 语法,它已被分组为(idCard[b].personName)[c].

但是,我很困惑为什么编译器要求我使用点表示法而不是指针表示法,因为我认为我将结构的地址传递到 *idCard 中,所以如果我没错的话,它应该是一个指针?

数组大多只是指向数组中第一个元素的指针(除了编译器可能知道数组大小)。

因为数组大多只是指针;对于整数数组myInt = myIntArray[x];就像myInt = *(myIntArray + x);-指针取消引用是由数组索引隐含的。请注意,要访问数组中int中间的char,您可以(不可移植地)使用myChar = *((char *)(myIntArray + x)) + offset_of_char_in_int);;这有点像访问结构数组中的字段(因为它们都在访问较大事物数组中的较小内容)。

对于结构数组;索引数组会导致取消引用(就像它对整数数组所做的那样);所以myIDcardStruct = idCard[i];就像myIDcardStruct = *(idcard + i);。由于数组索引具有隐含的取消引用,因此myIDcardStruct不是指针。

->运算符就像将请求的结构字段的偏移量添加到地址,将地址强制转换为请求字段的类型,然后取消引用。换句话说,myInt = myStructPointer->myIntField;就像myInt = (*myStructPointer).myIntField;就像tempAddress = (void *)myStructPointer + offset_of_myIntField; myInt = *((int *)tempAddress);

这意味着,如果你有一个结构数组(主要是指向数组中第一个结构的指针),索引数组会导致指针被隐式取消引用,并且使用->也会导致隐式取消引用;如果你两者都这样做,那么你已经(隐式地)取消引用了指针两次,这是太多的取消引用(因为它不是指向结构的指针的指针, 或指向结构的指针数组)。因为你只希望它取消引用,你必须在一个隐式顺从(数组索引)或另一个隐式反引用(->)之间进行选择;例如,您可以在myInt = idCard[i].nameCardID;myInt = (idCard + i)->nameCardID;之间进行选择。

当然,重要的是使代码易于阅读,myInt = idCard[i].nameCardID;myInt = (idCard + i)->nameCardID;更容易阅读。