C 动态内存和指针参数

C 动态内存和指针参数,c,function,pointers,C,Function,Pointers,我有两个函数,它们的作用是相同的——从一个只有整数的文件中读取每一行,并将它们存储在一个数组中: 我在main()函数中这样调用它们: StoreinArray1(X,大小,f) storeinaray2(X,大小,f) 第一个有效,但第二个无效 首先 int StoreinArray1(int X[], int *size, char *file) { int i=0; FILE *f; f = fopen(file, "r"); X = (int*) rea

我有两个函数,它们的作用是相同的——从一个只有整数的文件中读取每一行,并将它们存储在一个数组中:

我在main()函数中这样调用它们:

StoreinArray1(X,大小,f)

storeinaray2(X,大小,f)

第一个有效,但第二个无效

首先

int StoreinArray1(int X[], int *size, char *file)
{
    int i=0;
    FILE *f;
    f = fopen(file, "r");

    X = (int*) realloc (X, *size * sizeof(int));

for (i=0;i<*size;i++)
{
    fscanf(f, "%d", &X[i]);
}

return 1;
}
对于第一个
,我使用了动态内存分配和实际计算的大小:

 X = malloc(0); 

 while ((ch = fgetc(f)) != EOF)
{
    if (ch == '\n')
    lines++;
}

size = &lines;
就这一秒而言,我不能做同样的事。Visual Studio代码在我尝试时崩溃

所以我试着做
*size=0
,然后做
storeinaray2(X,size,f)但它也不起作用

所以我的问题是关于第二个函数:

它是否在扫描文件时计算大小?假设没有必要使用动态内存分配(我的老师说)

如果是这样的话,我如何才能正确地传递一些“大小”参数?作为一个指针还是一个简单的整数

提前谢谢你


编辑:

以下是完整的第一个程序:

#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *f;
int *size=0, *X, lines=1;
char *file = {"file.txt"};
char ch;

X = malloc(0);

f = fopen(file, "r");

while ((ch = fgetc(f)) != EOF)
{
    if (ch == '\n')
    lines++;
}

size = &lines;

  StoreinArray(X, size, file);

}

int StoreinArray(int X[], int *size, char *file)
{
int i=0;
FILE *f;
f = fopen(file, "r");

X = (int*) realloc (X, *size * sizeof(int));

for (i=0;i<*size;i++)
{
    fscanf(f, "%d", &X[i]);
}

for (i=0;i<*size;i++)
    printf("%d\n",X[i]);

return 1;
}

首先,我必须打开main中的文件来计算行数。我知道我在main中忘记了fclose(f)和free(X),但是根据这些指令,VSC崩溃了



程序的第二个版本的问题是main中的
size
声明。将其声明为int,而不是指向int的指针。您当前的程序正在崩溃,因为您没有为大小分配任何空间,并且当StoreInArray尝试更新它时,您遇到了访问冲突。所以,main应该是这样的:

int main()
{
    int X[100];
    int size;
    char *file = {"file.txt"};

    size = 0;

    StoreinArray(X, &size, file);
}

好的,我会尽力解释清楚,并解释我能找到的所有东西

首先,我们需要讨论变量、指针和内存,因为您似乎对这些概念没有很好的理解。一旦点击,其余的应该很容易跟随

首先,简单变量。那部分很简单,我想你或多或少都明白这一点

int x; // This is an integer variable. It's not initialized, so its value could be anything
int meaning = 42; // This is another integer variable. Its value will be 42.
double pi = 3.14; // A variable with digits after the decimal point
char c = 15; // Another inte... well, yes, actually, char is also an integer.
char c2 = 'a'; // Nice, this also counts. It's converted to an integer behind the scenes.
等等

与阵列类似:

int arr[10]; // Array with 10 values. Uninitialized, so they contain garbage.
int arr2[3] = { 1, 2, 3 }; // Array with 3 values, all initialized
int arr3[] = {1, 2, 3, 4, 5}; // Array with 5 values.
数组基本上只是一次创建的一组变量。创建数组时,C需要知道大小,并且大小必须是一个固定的数字-不能使用其他变量。这是有原因的,但这是技术性的,我不想再谈这个了

现在谈谈记忆。这些变量中的每一个都将存储在计算机的RAM中。精确的位置是不可预测的,每次运行程序时可能会有所不同

现在,RAM就像一个字节的huuuge数组。有字节数
0
、字节数
1
,等等。一个
int
变量占用4个字节,因此它可以,例如,以字节数
120
121
122
123
结束

单个变量(或单个数组)中的所有字节将在RAM中彼此相邻。两个不同的变量可能会在RAM的另一端结束,但每个变量中的字节将在一起

现在我们来讨论指针的概念。指针基本上只是一个整数变量。它包含其他变量的第一个字节的RAM号。让我们看一个例子:

int i = 42;
int *p = &i;
假设变量
i
存储在字节数
200
203
(即4个字节)中。在这些字节中,我们有值
42
。然后假设变量
p
存储在字节数
300
303
(这是另外4个字节)中。这4个字节将包含值
200
,因为这是
i
变量的第一个字节

这也是程序员在说“
的”(内存)地址”或“指向
的指针”时的意思。这是
的RAM中第一个字节的数目。因为同一变量的所有字节都粘在一起,所以通过知道第一个字节(以及知道变量的类型),您可以找出
的其余部分在内存中的位置

现在,让我们在示例中再添加一行:

*p = 5;
在这种情况下,计算机所做的是获取存储在
p
中的地址,进入内存中的该位置,将以下4个字节视为一个整数,并将值
5
放在那里。因为我们之前已将
p
设置为“点”“在地址
i
处,这与简单地设置
i
变量本身具有相同的效果

好的,你都明白了吗?这是一个有点棘手的问题,通常需要一段时间才能解决。为了理解它,请随时重读一遍。你需要它来继续前进

准备好了吗?好的,让我们谈谈堆栈和动态内存

当程序启动时,操作系统会自动为它分配一点内存,只是为了让它更容易启动。它就像一个大的字节数组,都在内存中。现在它通常是1MB左右,但它可以变化。这种内存称为“堆栈”。为什么这么叫?嗯,我改天再解释

不管怎么说,当你的
main()
函数启动时,操作系统会像“给你,我的好朋友,一个指向堆栈的指针。你认为合适的时候就可以使用它了!祝你有愉快的一天!”

然后,您的
main()
函数使用它来存储您在其中生成的所有变量。所以当你像
p=&i
那么存储在
p
中的地址就在堆栈的某个地方

现在,当
main()
调用另一个函数时,例如
StoreinArray()
,它也会给它一个指向堆栈的指针,并说“好的,这是指向堆栈的指针。小心,我已经使用了它的前XXX字节,但可以随意使用其余的”

然后
StoreinArray()
使用堆栈将其变量放在那里。当
StoreinArray()
调用其他对象时,它也会执行相同的操作,而且会不断地执行

现在,有几个
int arr[10]; // Array with 10 values. Uninitialized, so they contain garbage.
int arr2[3] = { 1, 2, 3 }; // Array with 3 values, all initialized
int arr3[] = {1, 2, 3, 4, 5}; // Array with 5 values.
int i = 42;
int *p = &i;
*p = 5;
#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *f;
int *size=0, *X, lines=1;
char *file = {"file.txt"};
char ch;

X = malloc(0);

f = fopen(file, "r");

while ((ch = fgetc(f)) != EOF)
{
    if (ch == '\n')
    lines++;
}

size = &lines;

  StoreinArray(X, size, file);

}

int StoreinArray(int X[], int *size, char *file)
{
int i=0;
FILE *f;
f = fopen(file, "r");

X = (int*) realloc (X, *size * sizeof(int));

for (i=0;i<*size;i++)
{
    fscanf(f, "%d", &X[i]);
}

for (i=0;i<*size;i++)
    printf("%d\n",X[i]);

return 1;
}
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *file = "file.txt";
    FILE *f = fopen(file, "r");
    int *X, lines=1;
    char ch;

    while ((ch = fgetc(f)) != EOF)
    {
        if (ch == '\n')
            lines++;
    }
    fclose(f);

    X = (int *)malloc(lines * sizeof(int));

    StoreinArray(X, lines, file);
}

void StoreinArray(int X[], int lines, char *file)
{
    int i=0;
    FILE *f = fopen(file, "r");

    for (i=0;i<lines;i++)
    {
        fscanf(f, "%d", &X[i]);
    }
    fclose(f);

    for (i=0;i<lines;i++)
        printf("%d\n",X[i]);
}
int main()
{
    int X[100];
    int *size;
  char *file = {"file.txt"};

  *size = 0;

  StoreinArray(X, size, file);
}
int StoreinArray(int X[], int *size, char *file)
{
  FILE *f;
  f = fopen(file, "r");
  if (f == NULL)
    return -1;
  *size = 0;
  while (!feof(f))
 {
    if (fscanf(f, "%d", &X[*size]) == 1)
      *size++;
  }
  fclose(f);
  return 1;
}
#include <stdio.h>
#include <stdlib.h>

#define MAX_X 100

int main()
{
    int X[MAX_X];
    char *file = "file.txt";
    int lines;

    lines = StoreinArray(X, MAX_X, file);
}
int StoreinArray(int X[], int maxLines, char *file)
{
    FILE *f;
    int lines;

    f = fopen(file, "r");
    if (f == NULL)
        return -1;

    while (!feof(f))
    {
        if (fscanf(f, "%d", &X[lines]) == 1)
            lines++;
        if (lines == maxLines)
            break;
    }
    fclose(f);
    return lines;
}