简体   繁体   English

是否将结构初始化为指针有什么区别?

[英]What's the difference between intializating a struct as pointer or not?

I have the following for my HashTable structure: 我的HashTable结构具有以下内容:

typedef char *HashKey;
typedef int HashValue;

typedef struct sHashElement {
    HashKey key;
    HashValue value;
} HashElement;

typedef struct sHashTable {
    HashElement *items;
    float loadFactor;
} HashTable;

I never really thought about it until now but I just realized there's two ways how I can use this: 直到现在我还没有真正考虑过它,但是我意识到有两种方法可以使用它:

Alternative 1: 选择1:

void hashInitialize(HashTable *table, int tabSize) {
    table->items = malloc(sizeof(HashElement) * tabSize);

    if(!table->items) {
        perror("malloc");
        exit(1);
    }

    table->items[0].key = "AAA";
    table->items[0].value = 45;
    table->items[1].key = "BBB";
    table->items[1].value = 82;

    table->loadFactor = (float)2 / tabSize;
}


int main(void) {
    HashTable t1;
    int i;

    hashInitialize(&t1, HASHSIZE);

    for(i = 0; i < HASHSIZE - 1; i++) {
        printf("PAIR(%d): %s, %d\n", i+1, t1.items[i].key, t1.items[i].value);
    }

    printf("LOAD FACTOR: %.2f\n", t1.loadFactor);

    return 0;
}

Alternative 2: 选择2:

void hashInitialize(HashTable **table, int tabSize) {
    *table = malloc(sizeof(HashTable));

    if(!*table) {
        perror("malloc");
        exit(1);
    }

    (*table)->items = malloc(sizeof(HashElement) * tabSize);

    if(!(*table)->items) {
        perror("malloc");
        exit(1);
    }

    (*table)->items[0].key = "AAA";
    (*table)->items[0].value = 45;
    (*table)->items[1].key = "BBB";
    (*table)->items[1].value = 82;

    (*table)->loadFactor = (float)2 / tabSize;
}


int main(void) {
    HashTable *t1 = NULL;
    int i;

    hashInitialize(&t1, HASHSIZE);

    for(i = 0; i < HASHSIZE - 1; i++) {
        printf("PAIR(%d): %s, %d\n", i+1, t1->items[i].key, t1->items[i].value);
    }

    printf("LOAD FACTOR: %.2f\n", t1->loadFactor);

    return 0;
}

Question 1: They both seem to produce the same result. 问题1:它们似乎都产生相同的结果。 On main , both examples print the right key/value pair. main ,两个示例均打印正确的键/值对。 So, what exactly is the different between them besides the syntax change (using (*table) instead of just table ), the extra code to allocate memory for the HashTable structure and the declaration of HashTable pointer? 那么,除了语法更改(使用(*table)而不是table ),为HashTable结构分配内存的额外代码以及HashTable指针的声明之外,它们之间到底有什么不同?

I've been writing a few data structures lately like stacks, linked lists, binary search trees and now hash tables. 我最近一直在写一些数据结构,例如堆栈,链接列表,二进制搜索树,现在是哈希表。 And for all of them, I've always used the alternative 2. But now I'm thinking if I could have used alternative 1 and simplify the code, removing most of the * and & that are all over the place. 对于所有这些,我一直使用替代项2。但是现在,我在考虑是否可以使用替代项1并简化代码,删除所有*&

But I'm asking this question to understand the differences between the two methods and if, and also why, I should use on over the other. 但是我问这个问题是为了了解这两种方法之间的区别,以及是否以及为什么我应该在另一种方法上使用。

Question 2: As you can see in the structures code, HashKey is a pointer. 问题2:您可以在结构代码中看到, HashKey是一个指针。 However, I'm not using strdup nor malloc to allocate space for that string. 但是,我没有使用strdupmalloc为该字符串分配空间。 How and why is this working? 这如何以及为什么起作用? Is this OK to do? 这样可以吗? I've always used malloc or strdup where appropriate when handling dynamic strings or I would get lots of segmentation faults. 在处理动态字符串时,我总是在适当的地方使用mallocstrdup ,否则会遇到很多分段错误。 But this code is not giving me any segmentation faults and I don't understand why and if I should do it like this. 但是这段代码并没有给我任何分割错误,而且我也不明白为什么以及是否应该这样做。

In alternative 1, the caller would allocate table but your function would allocate the contents thereof, which is not always a good idea in terms of memory management. 在替代方案1中,调用方将分配table但您的函数将分配其表内容,就内存管理而言,这并不总是一个好主意。 Alternative 2 keeps all allocations in the same place. 备选方案2将所有分配保留在同一位置。

As answered previously, the differences between the two alternatives is memory management. 如前所述,这两种选择之间的区别是内存管理。 In alternative 1 you expect the caller to allocate the memory for table prior to the call; 在备选方案1中,您希望调用者在调用之前为表分配内存; whereas, in alternative 2 just a pointer declaration is required to give you a place to put the memory after you've created it. 而在替代方案2中,只需要一个指针声明就可以在创建内存之后为您提供放置内存的位置。

To question 2, the simple answer is that you are assigning a constant to the string. 对于问题2,简单的答案是您正在为字符串分配一个常量。 According to the following site the assignment is set up at compile time, not runtime. 根据以下站点,分配是在编译时而不是运行时设置的。

http://publications.gbdirect.co.uk/c_book/chapter6/initialization.html http://publications.gbdirect.co.uk/c_book/chapter6/initialization.html

First both solutions are perfectly right ! 首先,两种解决方案都是完全正确的!

Alternative 1 : 备选方案1:

Your HashTable is declared in the main, which means the struct is somewhere in the call stack. 您的HashTable在main中声明,这意味着该结构在调用堆栈中的某个位置。 The struct will be destroy if you leave the scope. 如果离开示波器,该结构将被销毁。 Note : In your case that can't happen because the declaration is in the main so the scope ends on process exit. 注意:在这种情况下,由于声明位于主声明中,因此作用域在进程退出时结束,因此不会发生。

Alternative 2: 选择2:

You've got a HashTable* (pointer) in the call stack so you need to allocate the memory for the struct. 您在调用堆栈中有一个HashTable *(指针),因此您需要为结构分配内存。 To do so you use malloc. 为此,请使用malloc。

In both case your struct is correctly allocated. 在两种情况下,您的结构均已正确分配。 The main difference will be on performances. 主要区别在于表演。 It's far more performant to allocate on the stack but you can't do dynamic allocation. 在堆栈上分配性能要好得多,但是您不能进行动态分配。 To do so you need to use malloc. 为此,您需要使用malloc。 So, some times, you have to use malloc but try to avoid mallocing a lot if you want to do a high performance application. 因此,有时候,您必须使用malloc,但如果要执行高性能的应用程序,请尽量避免过多分配malloc。

Is that clear enough? 够清楚了吗? :) :)

for question 2: (*table)->items[0].key = "AAA"; 对于问题2:(* table)-> items [0] .key =“ AAA”;

actually puts "AAA" in read only parts of memory and char *key points to it, contents pointed by key cannot be changed. 实际上将“ AAA”放在内存的只读部分中,并且char * key指向它,不能更改key指向的内容。

(*table)->items[0].key[0]='a' gives and error (* table)-> items [0] .key [0] ='a'给出错误

Here you can find further discussion about it. 在这里您可以找到有关它的进一步讨论。

What is the difference between char s[] and char *s? char s []和char * s有什么区别?

唯一的区别是内存来自哪里-局部变量通常位于堆栈上,而malloc通常来自堆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 malloc 为结构指针分配内存和将结构指针指向结构的内存地址有什么区别? - What is the difference between using malloc to allocate memory to a struct pointer and pointing a struct pointer to a struct's memory address? 指针和指针变量之间有什么区别? - What's the difference between a pointer, and a pointer variable? struct {...}和struct {union {struct {...}}}之间有什么区别? - What's the difference between struct { … } and struct { union { struct { … } } }? char []和char *在struct中有什么区别? - What's the difference between char [] and char * in struct? 这些指针取消引用有什么区别 - What's the difference between these pointer dereferencements 分配指针和分配给元素或结构有什么区别? - what is the difference between allocation for a pointer, and allocation to element or struct? `typedef struct X {}`和`typedef struct {} X`有什么区别? - What's the difference between `typedef struct X { }` and `typedef struct { } X`? C指针:struc * A,struct * A和struct * A有什么区别? - C pointers: what's the difference between struc* A, struct *A and struct * A? 指针引用:数字1和2中的指针引用有什么区别? - Pointer referencing: What's the difference between pointer referencing in number 1 and 2. 空指针和void指针之间有什么区别? - What's the difference between a null pointer and a void pointer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM