2

我对 C 编程真的很陌生,我仍在尝试理解使用指针和使用 typedef 结构的概念。

我在下面有这个代码片段,我需要在程序中使用它:

typedef struct
{
    char* firstName;
    char* lastName;
    int id;
    float mark;
}* pStudentRecord;

我不确定这是做什么的——对我来说,这似乎与在 Objective-C 中使用接口相似,但我认为情况并非如此。

然后我有这条线

pStudentRecord* g_ppRecords;

我基本上需要根据一个数字添加pStudentRecord几个g_ppRecords。我了解如何为类型的对象创建和分配内存pStudentRecord,但我不确定如何实际将多个对象添加到g_ppRecords.

4

4 回答 4

2

定义了一个指向花括号中描述的结构的指针,这是一个更简单的示例

typedef struct {
    int x;
    int y;
}Point,* pPoint;

int main(void) {
   Point point = {4,5};
   pPoint point_ptr = &point;
   printf("%d - %d\n",point.x,point_ptr->x);

   pPoint second_point_ptr = malloc(sizeof(Point));
   second_point_ptr->x = 5;
   free(second_point_ptr);
}
于 2012-09-09T19:15:55.977 回答
2

第一个声明了一个未命名的结构,以及pStudentRecord一个指向它的类型。第二个声明g_ppRecords是指向 a 的指针pStudentRecord。换句话说,一个指向结构的指针的指针

将第二个视为“指针数组”可能更容易。因此,g_ppRecords[0]可能指向一个pStudentRecordg_ppRecords[1]另一个。(它又指向一个记录结构。)

为了添加它,您需要知道它是如何存储指针的,也就是说,如何知道其中存储了多少指针。某处有一个大小,对于 size N,意味着至少N * sizeof(pStudentRecord*)分配了内存,并g_ppRecords[0]通过g_ppRecords[N-1]保存N项目。或者,它是 NULL 终止的,对于 size N,意味着至少(N+1) * sizeof(pStudentRecord*)分配了内存并g_ppRecords[0]通过g_ppRecords[N-1]保存N项目,并g_ppRecords[N]持有NULL,标记字符串的结尾。

在此之后,创建或添加到g_ppRecords.

于 2012-09-09T19:21:23.883 回答
1

结构是一种复合数据类型,这意味着它是一个包含其他变量的变量。您熟悉 Objective C,因此您可能会认为它有点像“仅数据”类;也就是说,一个没有方法的类。这是一种将相关信息存储在一起的方法,您可以将这些信息作为一个单元传递。

Typedef 是一种让您将自己的数据类型命名为 C 中内置类型的同义词的方法。它使代码更具可读性并允许编译器捕获更多错误(您实际上是在向编译器教授更多关于程序意图的信息。 ) 经典的例子是

typedef int BOOL;

(旧的 ANSI C 中没有内置的 BOOL 类型。)

这意味着您现在可以执行以下操作:

BOOL state = 1;

并声明带BOOL参数的函数,然后让编译器确保您传递BOOLs,即使它们实际上只是ints:

void flipSwitch(BOOL isOn); /* function declaration */
...
int value = 0;
BOOL boolValue = 1;
flipSwitch(value); /* Compiler will error here */
flipSwitch(boolValue); /* But this is OK */

因此,您上面的 typedef 正在为学生记录结构创建同义词,因此您可以传递学生记录,而不必struct StudentRecord每次都调用它们。它使代码更清晰、更易读。除了这里还有更多,在你的例子中。我刚才描述的是:

typedef struct {
  char * firstName;
  char * lastName;
  int id;
  float mark;
} StudentRecord;

您现在可以执行以下操作:

StudentRecord aStudent = { "Angus\n", "Young\n", 1, 4.0 };

或者

void writeToParents(StudentRecord student) {
    ...
}

但是你有一个*在 typedef 之后。那是因为您要对包含指向 StudentRecord 的指针的数据类型进行 typedef,而不是对 StudentRecord 本身进行 typedef。诶?继续阅读...

你需要这个指向 StudentRecord 的指针,因为如果你想传递 StudentRecords 并能够修改它们的成员变量,你需要传递指向它们的指针,而不是变量本身。typedef 对此非常有用,因为编译器可以再次捕获细微的错误。上面我们所做writeToParents的只是读取 StudentRecord 的内容。假设我们想改变他们的成绩;我们无法使用简单的 StudentRecord 参数设置函数,因为我们无法直接更改成员。所以,我们需要一个指针:

void changeGrade(StudentRecord *student, float newGrade) {
  student->mark = newGrade;
}

很容易看出您可能会错过 *,因此,改为 typedef 为 StudentRecord 的指针类型,编译器将提供帮助:

typedef struct { /* as above */ } *PStudentRecord;

现在:

void changeGrade(PStudentRecord student, float newGrade) {
  student->mark = newGrade;
}

更常见的是同时声明两者:

typedef struct {
  /* Members */
} StudentRecord, *PStudentRecord;

这也为您提供了普通的 struct typedef 和指针 typedef。

那么什么是指针呢?一个变量,它将地址保存在另一个变量的内存中。听起来很简单;从表面上看确实如此,但它变得非常微妙并且很快就被卷入其中。试试这个教程

于 2012-09-09T19:28:58.500 回答
0

这定义了指向结构的指针的名称,而不是结构本身的名称。尝试更改为:

typedef struct
{
    char* firstName;
    char* lastName;
    int id;
    float mark;
} StudentRecord;

StudentRecord foo;
StudentRecord *pfoo = &foo;
于 2012-09-09T19:08:20.557 回答