【问题标题】:In C arrays are not assignable so why is this program working?在 C 中,数组是不可分配的,那么为什么这个程序可以工作?
【发布时间】:2018-05-16 16:51:19
【问题描述】:

在 C 中,数组不可赋值,但在第 36 行(我也评论过的行)中,我为数组 name 赋值,而没有出现任何错误。为什么会这样?另外,如果您检查我的 freeStudents 功能是否正常工作,除了这个令人费解的事情之外,我真的很感激。谢谢你们的时间!

#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME 50

struct students
{
    char name[MAX_NAME];
    float average;
};

void storeStudents(struct students *lst, int n);
void printStudents(struct students *lst, int n);
void freeStudents(struct students *lst);

int main(void)
{
    int n;
    printf("How many students you wanna store? ");
    scanf("%d", &n);
    struct students *list;
    list = (struct students *)malloc(n*sizeof(struct students));

    storeStudents(list,n);
    printStudents(list,n);
    freeStudents(list);

    return 0;
}

void storeStudents(struct students *lst, int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        printf("Name of student: ");
        scanf("%s", &(lst[i].name)); //In C arrays are not assignable, so why is this line working?
        printf("Average of student: ");
        scanf("%f", &(lst[i].average));
    }
    printf("\n");
}

void printStudents(struct students *lst, int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        printf("Name: %s\tAverage: %.2f", lst[i].name, lst[i].average);
        printf("\n");
    }
}

void freeStudents(struct students *lst)
{
    free(lst);
}

【问题讨论】:

  • 如果你启用编译器警告,你会看到真正发生了什么:ideone.com/7JPJFH
  • Oliver Charlesworth 代码块编译器没有给我任何警告/错误..
  • “在 C 中的数组不可赋值”是什么意思?数组包含的内容显然是可变的,因此您可以为它的元素分配一个新值。您在哪里读到“数组不可分配”?
  • @LasseVågsætherKarlsen - 数组确实是不可赋值的,因为如果a 是数组类型,你不能做a = b;
  • Lasse Vågsæther Karlsen,我在 stackoverflow 帖子中读到数组不可在 c 中分配(最佳投票答案)。看看:stackoverflow.com/questions/1292586/…

标签: c


【解决方案1】:

在 C 中,您不能将数组分配给另一个数组,主要是因为数组不能位于分配的左侧。所以如下:

char a[5] = { 1, 2, 3, 4, 5 };
char b[5];
b = a; 

不正确。但当然这是正确的:

b[0] = a[0]; 
b[1] = a[1]; 
b[2] = a[2]; 
b[3] = a[3]; 
b[4] = a[4]; 

因为b[0](即*(b+0))不是数组,而是char

现在进入重点。在第 36 行,您可以:

scanf("%s", &(lst[i].name));

剖析前的评论:请勿使用scanf() 进行用户输入。

无论如何,该函数是一个可变参数函数,这意味着它会愉快地接受您作为第二个参数传递的任何内容。但是您应该传递的是char*(指向char 的指针)。为什么?因为设计函数的人是这样决定的:当格式字符串有 %s 时,你需要一个 char* 参数。

&amp;(lst[i].name) 是什么类型?表达式lst[i].name 的类型为char[50](50 个字符的数组),所以&amp;(lst[i].name) 是“50 个字符的数组的地址”,在C 中称为“指向50 个字符的数组的指针”或 C 语法 char(*)[50]。这不是char*。所以这是错误的或更好的未定义行为。

正确的版本应该是什么?嗯,这个:

scanf("%s", lst[i].name);

因为当您在表达式中使用数组时,它衰减为指向第一个元素的指针。

好的,但为什么它仍然有效?它可能在某些编译器上工作,因为它们在两种情况下都只传递数组的地址,所以在堆栈上两者都是相同的数字。

最后,在这个表达式语句中没有“分配”数组,因此这个问题实际上首先没有任何意义。或者更好的是,该函数接收数组的地址,并使用指向第一个元素的指针填充它。另一个有趣的事情是你不能拥有带有数组参数的函数。只有指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    相关资源
    最近更新 更多