一些初学C问题

时间:2009-09-10 21:00:11

标签: c struct pointers

我有点学习C,我不是编程的初学者,我“知道”Java和python,顺便说一下我在mac(豹子)上。 首先,

1 :当使用指针时,有人可以解释吗?何时不能?

2

char *fun = malloc(sizeof(char) * 4);

char fun[4];

char *fun = "fun";

然后除了最后一个之外的所有内容都将索引0,1,2和3分别设置为'f','u','n'和'\ 0'。我的问题是,为什么第二个不是指针?为什么char fun [4]而不是char * fun [4]?为什么看起来结构或int的指针总是一个数组呢?

第3 : 我理解这一点:

typedef struct car
{
    ...
};

的快捷方式
struct car
{
    ...
};
typedef struct car car;

正确?但我真的很困惑:

typedef struct A
{
    ...
}B;

A和B有什么区别? A是'标签名',但那是什么?我什么时候使用哪个?枚举也一样。

4 即可。我理解指针的作用,但我不明白它们的意义(没有双关语)。什么时候在堆栈和堆上分配一些东西?我如何知道它的分配位置?指针与它有关吗?

5 即可。最后,知道C游戏编程的任何好教程(简单)?对于mac / OS X,不是windows?

PS。是否有人用来引用C而不是C ++的其他名称?我讨厌他们的名字几乎都是同一个东西,所以很难尝试谷歌特别是C而不仅仅是获得C ++和C#的东西。

谢谢!

很难找到最好的答案,他们都很棒,但我选择的那个是让我理解我的第三个问题的唯一一个,这是我原本要问的唯一一个。再次感谢!

6 个答案:

答案 0 :(得分:4)

  

我的问题是,为什么第二个不是指针?

因为它声明了一个数组。在另外两种情况下,您有一个指针,指向其他位置的数据。但是,您的数组声明声明了一个数据数组,它位于声明的位置。如果您在函数中声明它,那么当您从该函数返回时数据将会死亡。最后char *fun[4]将是一个4指针数组 - 它不会是一个char指针。如果你只是想指向一个包含4个字符的块,那么char*就足够了,不需要告诉它确实有4个字符要指向。

如果您需要从其上生存数据直到匹配的free调用,则会使用在堆上创建对象的第一种方法。数据将从函数返回后继续存在。

最后一种方法只是创建不打算写入的数据。它是一个指向字符串文字的指针 - 它通常存储在只读存储器中。如果你写它,那么行为是未定义的。

  

我理解指针的作用,但我不明白它们的意义(没有双关语意)。

指针用来表示某些东西(当然没有双关语)。看看它是这样的:如果桌子上有一排物品,而你的朋友说“挑选第二件物品”,那么物品就不会神奇地走向你。你必须抓住它。你的手就像一个指针,当你把手移回给你时,你取消引用那个指针并获得该项目。项目行可以看作是一系列项目:

  

看来结构或int的指针总是一个数组呢?

item row[5];

当您执行item i = row[1];时,您首先将手指向第一个项目(获取指向第一个项目的指针),然后您前进直到您处于第二个项目。然后你把这个项目带回给你:)所以,row[1]语法不是数组特有的,而是指针特有的 - 它相当于*(row + 1),并且制作了一个临时指针当你使用这样的数组时。

  

A和B有什么区别? A是'标签名',但那是什么?我什么时候使用哪个?枚举也一样。

typedef struct car
{
    ...
};

这不是有效的代码。您基本上说“通过以下普通标识符定义类型struct car { ... }”,但您错过了告诉标识符。就我所见,以下两个片段是等效的

<强> 1)

struct car
{
    ...
};
typedef struct car car;

<强> 2)

typedef struct car
{
    ...
} car;
  

A和B有什么区别? A是'标签名',但那是什么?我什么时候使用哪个?枚举也一样。

在我们的例子中,标识符car在同一范围内被声明了两次。但声明不会发生冲突,因为每个标识符都位于不同的名称空间中。涉及的两个名称空间是普通名称空间标记名称空间。需要在 struct union enum 关键字之后使用标记标识符,而普通标识符不需要任何内容​​。您可能听说过POSIX函数stat,其界面如下所示

struct stat {
  ...
};

int stat(const char *path, struct stat *buf);

在该代码段中,stat也注册到上述两个命名空间中。 struct stat将引用结构,仅stat将引用该函数。有些人不喜欢始终在structunionenum之前添加标识符。那些使用typedef来引入一个引用结构的普通标识符。标识符当然可以是相同的(两次car),也可以不同(一次A另一次B)。没关系。

答案 1 :(得分:2)

3)使用两个不同的名字A和B是不好的风格:

typedef struct A
{
    ...
} B;

根据该定义,您可以说

struct A a;
B b;
b.field = 42;
a.field = b.field;

因为变量a和b具有相同的类型。 C程序员通常会说

typedef struct A
{
  ...
} A;

这样您就可以使用“A”作为类型名称,相当于“struct A”,但它可以节省大量的输入。

答案 2 :(得分:2)

  1. 在需要时使用它们。阅读更多示例和教程,直到您了解 指针是什么,这应该更加清晰:)
  2. 第二种情况在内存中创建一个数组,空间为四个字节。当您使用该数组的名称时,您会神奇地返回指向第一个(索引0)元素的指针。然后[]运算符实际上处理指针,而不是数组 - x[y]等同于*(x + y)。是的,这意味着x[y]y[x]相同。对不起。
    还要注意,当你向指针添加一个整数时,它会乘以指向元素的大小,所以如果你做someIntArray[1],你得到第二个(索引1)元素,而不是从中间的某个位置开始第一个字节 此外,作为函数参数列表中的最终问题 - 数组类型 - 例如,void foo(int bar[4]) - 秘密地转换为指针类型 - 即void foo(int *bar)。这只是 函数参数中的情况。
  3. 您的第三个示例声明了一个包含两个名称的结构类型 - struct AB。在纯C中,struct必须A - 在C ++中,您可以将其称为AB。除了名称更改之外,这两种类型完全等效,您可以随时随地替换其中一种,而不会改变行为。
  4. C有三个地方可以存储:

    • 堆栈 - 函数中的局部变量在这里。例如:

      void foo() {
          int x; // on the stack
      }
      
    • 当您使用malloccallocrealloc明确分配堆时,堆就会显示在此处。

      void foo() {
          int *x; // on the stack
          x = malloc(sizeof(*x)); // the value pointed to by x is on the heap
      }
      
    • 静态存储 - 全局变量和static变量,在程序启动时分配一次。

      int x; // static
      void foo() {
          static int y; // essentially a global that can only be used in foo()
      }
      
  5. 不知道。我希望我不需要立即回答所有问题 - 这就是你应该将它们分开的原因:)

  6. 注意:由于某种降价错误,格式看起来很难看,如果有人知道解决方法,请随时编辑(并删除此注释!)

答案 3 :(得分:0)

  

char * fun = malloc(sizeof(char)* 4);
  要么   char fun [4];
  要么   char * fun =“fun”;

第一个可以在运行时设置为您想要的任何大小,并在以后调整大小 - 您也可以在完成后释放内存。 第二个是指针真的很“有趣”和char ptr =&amp; fun [0]相同。

  

我理解指针的作用,但我不明白有什么意义   他们是(没有双关语)。什么时候   做了什么分配在   堆栈与堆?我怎么知道   在哪里分配?做指针   与它有关系吗?

当你在像“char fun [4]”这样的函数中定义某些内容时,它会在堆栈上定义,并且内存在函数外部不可用。 使用malloc(或C ++中的new)保留堆上的内存 - 您可以通过将指针传递给程序中的任何位置来使这些数据可用。这也允许您在运行时决定内存的大小,最后堆栈的大小是有限的(通常为1Mb),而在堆上,您可以保留所有可用的内存。

编辑5.不是真的 - 我会说纯C. C ++(几乎)是C的超集,所以除非你在一个非常有限的嵌入式系统上工作,否则通常可以使用C ++。

答案 4 :(得分:0)

在你的第二个问题中:

char *fun = malloc(sizeof(char) * 4);

VS

char fun[4];

VS

char *fun = "fun";

这些都包含4个字符的数组,但这就是相似性结束的地方。它们的不同之处在于这些字符的生命周期,可修改性和初始化。

第一个创建一个名为pointer to char的{​​{1}}对象 - 此指针变量仅在此函数启动时生效,直到函数返回。它调用C标准库并要求它动态创建一个4个字符数组大小的内存块,并将块中第一个字符的位置分配给fun。这个内存块(你可以看作是一个包含4个字符的数组)具有灵活的生命周期,这完全取决于程序员 - 直到你将该内存位置传递给fun为止。请注意,这意味着free()创建的内存块可以比指针变量malloc本身更长或更短的时间生存。另请注意,fun与该内存块之间的关联不固定 - 您可以更改fun,使其指向不同的内存块,或者使指针指向该内存块。

还有一件事 - 由fun创建的4个字符数组未初始化 - 它包含垃圾值。

第二个示例只创建一个对象 - 一个包含4个字符的数组,称为malloc。 (要测试此项,请将4更改为40并打印出fun)。这个数组只存在于它返回的函数返回之前(除非它在函数之外声明,当它在整个程序运行时存活)。这个4个字符的数组也没有初始化。

第三个例子创建了两个对象。第一个是一个名为sizeof(fun)的指向char的变量,就像在第一个例子中一样(和往常一样,它从这个函数的开始开始直到它返回)。另一个对象有点奇怪 - 它是一个由4个字符组成的数组,初始化为fun,其中没有名称,只要整个程序正在运行,它就会存在。它也保证可以修改(虽然如果你试图修改它会发生什么事情完全未定义 - 它可能会使程序崩溃,或者它可能不会崩溃)。变量{ 'f', 'u', 'n', 0 }初始化为这个奇怪的未命名,不可修改的长寿命数组的位置(但就像在第一个例子中,这种关联不是永久的 - 你可以使fun指向某个东西其他人)。

数组和指针之间存在如此多的令人困惑的相似点和不同点的原因可归结为两件事:

  • C中的“数组语法”(fun运算符)实际上适用于指针,而不是数组!
  • 试图确定数组的位置有点像捕捉雾 - 几乎在所有情况下,数组都会蒸发,而是被指向第一个元素的指针替换。

答案 5 :(得分:0)

\ 5。 Chipmunk

  • C中快速轻量的2D刚体物理库。

  • 专为2D视频游戏而设计。

  • 轻量级C99实现,在Std之外没有外部依赖。 C库。

  • 许多语言绑定可用。

  • 简单,请阅读文档并查看!

  • 无限制的麻省理工学院执照。

  • 让你更聪明,更强大,更有吸引力的异性!

  • ...