0

誰でも次のコードで私を助けてもらえますか? プログラムは正しく実行されます。

これらは私の質問です:

  1. cでドット演算子が機能するのはなぜですか?
  2. s11 つの構造体に十分なメモリしか割り当てていないのに、スタック構造体 (つまり ) に 2 回アクセスできるのはなぜですか? どのようにして配列になったのですか?
  3. ここでメモリがどのように割り当てられるのか、誰か説明してもらえますか?

コード:

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

typedef struct
{    
    struct mynode
    {
        int val;
        struct mynode *next;    
    } node;        
} stack;

int main()
{
    stack *s1;
    s1=(stack*)malloc(sizeof(stack));


    s1[0].node.val=10;
    s1[1].node.val=20;
    printf("%d",s1[1].node.val);

    getch();
    return 0;
}
4

4 に答える 4

10
  1. 私はあなたが何を意味するのか分かりません。ドット演算子は、構造体のメンバーにアクセスします。それがその機能です。
  2. あなたは違法なことをしているのです。Cには、悪いことをするのを止めるメカニズムはありませんが、「十分に」悪いことをするとプログラムがクラッシュします。ここで幸運に恵まれます。配列にはなりませんでした。配列のように扱っているだけです。コンパイラは、それが 1 つの要素へのポインターなのか、複数の要素 (配列) へのポインターなのかを判断できないため、任意のポインターを配列のように扱うことができます。それが有効であることを確認するのはあなた次第です。
  3. malloc。
于 2012-07-13T21:27:56.177 に答える
1

1)Cのドット演算子は、構造体のメンバーにアクセスできるようにする単なる言語構造です。構造体のメンバーにアクセスするために使用しているので、完全に合法です。機能しない理由はありません。

C#では、「。」を使用することもできます。オブジェクト内の関数を呼び出します。つまり、C#で次のクラスがある場合

public class foo()
{
  public void print_hello()
  {
    Console.Writeline("Hello,World");
  }  

 }

次のように使用します。

foo object1 = new foo();
foo.print_hello();

2)

この線

  stack *s1 

s1を構造体statへのポインタとして宣言しますが、これで終わりではありません。これを使用して、それぞれがスタック構造体を含むメモリの複数の領域を指すことができます。

配列(たとえば、intの配列)を宣言すると、従来の方法で宣言できます。

int  integersArray [10];

(このようにして、プログラムはメモリを自動的に割り当てます。心配する必要はありません)。ポインタを使用することもできます。その場合、配列を次のように宣言します。

  int * integersArray;

これは、割り当て方法に応じて、メモリの1つまたはさまざまなセグメントへのポインタになります。上記のコードは、前のコードとは異なり、メモリを割り当てず、構造体へのポインタを宣言するだけであることに注意してください。次のようにして、メモリを明示的に割り当てる必要があります。

  integersArray = malloc(10*sizeOf(int)); 

Wichは、intの10倍のサイズ、つまり10個の整数を保持するのに十分なメモリを割り当てます。どちらの場合も、integersArrayを通常の配列とコードとして使用できます

printf("%d",integersArray[0]);

動作します。2番目のケースでは、ポインターをインクリメントまたはデクリメントすることにより、配列内を移動できます。することによって

integersArray++

ポインタを次のメモリセクションに移動しています。integersArray+=11を実行する場合。、配列に10の位置がある場合、メモリの無効なセグメントになり、何かが発生する可能性があります(保護されたメモリセグメントに入ると、上記のコメントで指摘されているように、プログラムは終了します)。

@Alex:セグメンテーション。彼のランダムなポインタの逆参照が(偶然に)彼のメモリセグメント内にある限り、Cは文句を言わず、そのメモリ位置にあるゴミを受け取ります。彼が自分のセグメントの外に到達するとすぐに、カーネルは彼のプロセスを強制終了する可能性があります。–jforberg1時間前

あなたのプログラムは基本的に同じことをしていますが、代わりにs1を使用しています。

3)コードのこの部分

s1=(stack*)malloc(sizeof(stack));

タイプスタックの1つの構造を保持するのに十分なメモリを割り当てています。一般に、n個の要素にメモリを割り当てるには

yourPointer = malloc(n*sizeof(structure));

では、このように構造にアクセスしようとすると、なぜプログラムが機能するのでしょうか。

     s1[1].node.val=20;
    printf("%d",s1[1].node.val);

幸運にも有効なメモリにアクセスできると思いますが、必ずしもそうとは限りません。動的メモリを扱うときは、細心の注意を払うことをお勧めします。

注:上記が十分に明確であったとしても、K&Rの本をチェックすることを強くお勧めします。

于 2012-07-14T02:03:26.380 に答える
0

このコードを使用すると、構造体が1つだけ割り当てられます。

s1=(stack*)malloc(sizeof(stack));

2つの割り当てについては、次を試してください。

s1=(stack*)malloc(sizeof(stack) * 2);

于 2012-07-13T21:35:11.277 に答える
0

このコードは、あなたが書いているものよりも詳細です。これを設定することから始めますが、C で「リンクされたリスト」のトピックを調べることをお勧めします。これはスタックのようにはまったく機能しないためです。

実装を開始するための構造体のコードを次に示します。これはあなたの場合には機能しますが、続行したい場合は、初期化子と addNode 関数を作成することをお勧めします。リンク リストの詳細については、次のリンクを参照してください: http://www.codeproject.com/Articles/24684/How-to-create-Linked-list-using-CC

#include "stdlib.h"
#include "stdio.h"
typedef struct _node_ {
    int val;
    struct _node_ * next;
}mynode;

typedef struct _linkedlist_ {
    mynode * node;
}linkedlist;


int main() {
linkedlist * s1 = (linkedlist*) malloc(sizeof(linkedlist));
s1->node = malloc(sizeof(mynode));
s1->node->next = malloc(sizeof(mynode));
s1->node->val = 10;
s1->node->next->val = 20;
printf("%d",s1->node->next->val);
free(s1->node->next);
free(s1->node);
free(s1);
//getch(); //don't know what this is for
return 0;

}

于 2012-07-13T21:57:33.733 に答える