您的位置:首页 > 其它

Understanding and using c pointers 第六章读书笔记

2013-09-18 16:30 295 查看
tonybai在他的网站上写了一个本书的知识点纲要

结构声明的两种方式

1.使用struct关键字

struct _person
{
char* firstName;
char* lastName;
char* title;
unsigned int age;
};

2.使用类型定义(type definition)

typedef struct _person
{
char* firstName;
char* lastName;
char* title;
unsigned int age;
}Person;


结构的内存是如何分配的(How Memory Is Allocated for a Structure)

当给一结构分配内存时,给结构所分配的内存最小要是其单独字段(individual fields)所占内存的总和.然而因为结构字段之间可能发生内存填补其内存分配大小常大于该和.这些补齐常常是由于特定数据类型需要于特定内存边界对齐.例如,short总是对齐在地址能被2整除的地址上,一个整型需要对其在能被4整除的地址上.原文如下:

When a structure is allocated memory, the amount allocated to the structure is at minimum the sum of the size of its individual fields. However, the size is often larger than

this sum because padding can occur between fields of a structure. This padding can result from the need to align certain data types on specific boundaries. For example, a short is typically aligned on an address evenly divisible by two while an integer is aligned
on an address even divisible by four.

Several implications are related to this allocation of extra memory:

• Pointer arithmetic must be used with care //指针的算术运算时要当心

• Arrays of structures may have extra memory between their elements //

例如上述Person结构分配内存时会分配16字节,每个元素分配4字节.下面的AlternatePerson也占用四字节,这是因为结构尾部填补了2个字节

typedef struct _alternatePerson
{
char* firstName;
char* lastName;
char* title;
short age;
} AlternatePerson;

可以如下测试:

Person person;
AlternatePerson otherPerson;
printf("%d\n",sizeof(person));	//显示16
printf("%d\n",sizeof(otherPerson));//显示16

如果我们创建一个AlternatePerson数组,数组元素之间就会有填补(padding)

AlternatePerson people[30];

如图:



结构内存释放问题(Structure Deallocation Issues)

当为结构分配内存时,运行时系统不会自动为结构内部定义的指针分配内存,同样地,结构使用完毕后运行时系统也不会自动回收分配给结构指针的内存

下面的Person,结构在回收时,firstName,lastName,title里就变成了垃圾(will contain garbage)

typedef struct _person
{
char* firstName;
char* lastName;
char* title;
unsigned int age;
}Person;

结构的初始化
void initializePerson(Person *person,const char* fn,const char* ln,const char* title,unsigned int age)
{
person->firstName = (char *) malloc(strlen(fn) + 1);
strcpy(person->firstName,fn);

person->lastName = (char*) malloc(strlen(ln) + 1);
strcpy(person->lastName,ln);

person->title = (char*) malloc(strlen(title) + 1);
strcpy(person->title,title);

person->age = age;
}

void deallocatePerson(Person *person)
{
free(person->firstName);
free(person->lastName);
free(person->title);
}

void processPerson()
{
Person person;
initializePerson(person,"marble","matrix3d","porn",32);
...
deallocatePerson(person);	//用完后必须释放
free(person);
}

这样的初始化与释放类似于C++等中的构造函数和析构函数

避免malloc/free的开销

当结构体被反复的创建与回收时,就会需要产生一些开销(overhead),造成潜在的重大性能问题.一种方法就是维护自己所分配结构的列表,其实就是结构池之类的东西.
#define LIST_SIZE 10
Person* list[LIST_SIZE];

void initializeList()
{
int i;
for(i = 0; i < LIST_SIZE; i++)
{
list[i] = NULL;
}
}

Person* getPerson()
{
int i;
for(i = 0; i < LIST_SIZE; i++)
{
if(list[i] != NULL)
{
Person *ptr = list[i];
list[i] = NULL;
return ptr;
}
}
Person* person = (Person*) malloc(sizeof(Person));
return person;
}

Person* returnPerson(Person* person)
{
int i;
for(i = 0; i < LIST_SIZE; i++)
{
if(list[i] == NULL)
{
list[i] = person;
return person;
}
}
deallocatePerson(person);
free(person);
return NULL;
}

//使用方法
initializeList();
Person* ptrPerson;
ptrPerson = getPerson();
initializePerson(ptrPerson,"xc","xc","sdsd",56);
displayPerson(*ptrPerson);
returnPerson(ptrPerson);


使用指针来支持数据结构

指针可为简单或者复杂的数据结构提供很大的灵活性

作者这里讨论了4种数据结构单链表,队列,栈和二叉树

作者结合函数指针展示了处理泛型结构(generic structure)的能力

下面是一些数据结构的实现:

/**
*
* 列表实现
* 使用gcc编译通过
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _employee
{
char name[32];
unsigned char age;
} Employee;

int compareEmployee(Employee *e1,Employee *e2)
{
return strcmp(e1->name,e2->name);
}

void displayEmployee(Employee* employee)
{
printf("%s\t%d\n",employee->name,employee->age);
}

typedef void(*DISPLAY)(void*);
typedef int(*COMPARE)(void*,void*);

typedef struct _node
{
void *data;
struct _node *next;
} Node;

typedef struct _linkList
{
Node *head;
Node *tail;
Node *current;
} LinkedList;

void initializeList(LinkedList *list)
{
list->head = NULL;
list->tail = NULL;
list->current = NULL;
}

/*将节点添加到链表头部*/
void addHead(LinkedList *list,void *data)
{
Node *node = (Node *) malloc(sizeof(Node));
node->data = data;
if(list->head == NULL)
{
list->tail = node;
node->next = NULL;
}
else
{
node->next = list->head;
}
list->head = node;
}

void addTail(LinkedList *list,void *data)
{
Node *node = (Node *) malloc(sizeof(Node));
node->data = data;
node->next = NULL;
if(list->head == NULL)
{
list->head = node;
}
else
{
list->tail->next = node;
}
list->tail = node;
}

/*这里的Compare为函数添加了很高的灵活性*/
Node *getNode(LinkedList *list, COMPARE compare,void *data)
{
Node *node = list->head;
while(node != NULL)
{
if(compare(node->data,data) == 0)
{
return node;
}
node = node->next;
}
return NULL;
}

/*没有检查null指针之类的*/
void delete(LinkedList *list,Node *node)
{
if(node == list->head)
{
if(list->head->next == NULL)
{
list->head = list->tail = NULL;
}
else
{
list->head = list->head->next;
}
}
else
{
Node* tmp = list->head;
while(tmp != NULL && tmp->next != node)
{
tmp = tmp->next;
}
if(tmp != NULL)
{
tmp->next = node->next;
}
}
free(node);
}

void displayLinkList(LinkedList *list,DISPLAY display)
{
printf("\nLinked List\n");
Node *current = list->head;
while(current != NULL)
{
display(current->data);
current = current->next;
}
}

main()
{
LinkedList linkedList;
initializeList(&linkedList);

Employee *samuel = (Employee*) malloc(sizeof(Employee));
strcpy(samuel->name,"Samuel");
samuel->age = 32;

Employee *sally = (Employee*) malloc(sizeof(Employee));
strcpy(sally->name,"Sally");
sally->age = 28;

Employee *susan = (Employee*) malloc(sizeof(Employee));
strcpy(susan->name,"Susan");
susan->age = 45;

/*addHead函数的使用*/
addHead(&linkedList,samuel);
addHead(&linkedList,sally);
addHead(&linkedList,susan);

/*addTail函数的使用*/
addTail(&linkedList,sally);
addTail(&linkedList,susan);
addTail(&linkedList,samuel);

Node *node = getNode(&linkedList,(COMPARE)compareEmployee,sally);

Employee* e = (Employee*)node->data;
printf("%d\n",((Employee)(*e)).age);

printf("%s\n",(*((Employee*) linkedList.head->data)).name);
printf("%s\n",(*((Employee*) linkedList.tail->data)).name);
printf("node to delete %s\n",(*((Employee*) node->data)).name);

printf("\nbefore delete node");
/*使用函数指针避免了强转*/
displayLinkList(&linkedList,(DISPLAY)displayEmployee);

/*删除节点*/
delete(&linkedList,node);

printf("\nafter delete node");
displayLinkList(&linkedList,(DISPLAY)displayEmployee);
}


/**
*
* 作者使用了链表来实现队列
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _employee
{
char name[32];
unsigned char age;
} Employee;

int compareEmployee(Employee *e1,Employee *e2)
{
return strcmp(e1->name,e2->name);
}

void displayEmployee(Employee* employee)
{
printf("%s\t%d\n",employee->name,employee->age);
}

typedef void(*DISPLAY)(void*);
typedef int(*COMPARE)(void*,void*);

typedef struct _node
{
void *data;
struct _node *next;
} Node;

typedef struct _linkList
{
Node *head;
Node *tail;
Node *current;
} LinkedList;

void initializeList(LinkedList *list)
{
list->head = NULL;
list->tail = NULL;
list->current = NULL;
}

/*队列定义*/
typedef LinkedList Queue;

/**初始化队列*/
void initializeQueue(Queue *queue)
{
initializeList(queue);
}

/*将节点添加到链表头部*/
void addHead(LinkedList *list,void *data)
{
Node *node = (Node *) malloc(sizeof(Node));
node->data = data;
if(list->head == NULL)
{
list->tail = node;
node->next = NULL;
}
else
{
node->next = list->head;
}
list->head = node;
}

void enqueue(Queue *queue,void *node)
{
addHead(queue,node);
}

/*
* 之前实现的链表没有明确的函数删除尾节点,下面的 dequeue函数移出尾节点
*/
void *dequeue(Queue *queue)
{
Node *tmp = queue->head;
void *data;
if(queue->head == NULL)
{
data = NULL;
}
else if(queue->head == queue->tail)
{
queue->head = queue->tail = NULL;
data = tmp->data;
free(tmp);
}
else
{
while(tmp->next != queue->tail)
{
tmp = tmp->next;
}
queue->tail = tmp;
tmp = tmp->next;
queue->tail->next = NULL;
data = tmp->data;
free(tmp);
}
return data;
}

main()
{
Queue queue;
initializeList(&queue);

Employee *samuel = (Employee*) malloc(sizeof(Employee));
strcpy(samuel->name,"Samuel");
samuel->age = 32;

Employee *sally = (Employee*) malloc(sizeof(Employee));
strcpy(sally->name,"Sally");
sally->age = 28;

Employee *susan = (Employee*) malloc(sizeof(Employee));
strcpy(susan->name,"Susan");
susan->age = 45;

enqueue(&queue,samuel);
enqueue(&queue,sally);
enqueue(&queue,susan);

void *data = dequeue(&queue);
printf("Dequeued %s\n",(*(Employee*)data).name);

data = dequeue(&queue);
printf("Dequeued %s\n",(*(Employee*)data).name);

data = dequeue(&queue);
printf("Dequeued %s\n",(*(Employee*)data).name);
}


/**
*
* 作者使用了链表来实现栈
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _employee
{
char name[32];
unsigned char age;
} Employee;

int compareEmployee(Employee *e1,Employee *e2)
{
return strcmp(e1->name,e2->name);
}

void displayEmployee(Employee* employee)
{
printf("%s\t%d\n",employee->name,employee->age);
}

typedef void(*DISPLAY)(void*);
typedef int(*COMPARE)(void*,void*);

typedef struct _node
{
void *data;
struct _node *next;
} Node;

typedef struct _linkList
{
Node *head;
Node *tail;
Node *current;
} LinkedList;

void initializeList(LinkedList *list)
{
list->head = NULL;
list->tail = NULL;
list->current = NULL;
}

/*栈定义*/
typedef LinkedList Stack;

/**初始化栈*/
void initializeStack(Stack *stack)
{
initializeList(stack);
}

/*将节点添加到链表头部*/
void addHead(LinkedList *list,void *data)
{
Node *node = (Node *) malloc(sizeof(Node));
node->data = data;
if(list->head == NULL)
{
list->tail = node;
node->next = NULL;
}
else
{
node->next = list->head;
}
list->head = node;
}

void push(Stack *stack,void *data)
{
addHead(stack,data);
}

/*
* 之前实现的链表没有明确的函数删除尾节点,下面的 dequeue函数移出尾节点
*/
void *pop(Stack *stack)
{
Node *node = stack->head;
if(node == NULL)
{
return NULL;
}
else if(node == stack->tail)
{
stack->head = stack->tail = NULL;
void *data = node->data;
free(node);
return data;
}
else
{
stack->head = stack->head->next;
void *data = node->data;
free(node);
return data;
}
}

main()
{
Stack queue;
initializeList(&queue);

Employee *samuel = (Employee*) malloc(sizeof(Employee));
strcpy(samuel->name,"Samuel");
samuel->age = 32;

Employee *sally = (Employee*) malloc(sizeof(Employee));
strcpy(sally->name,"Sally");
sally->age = 28;

Employee *susan = (Employee*) malloc(sizeof(Employee));
strcpy(susan->name,"Susan");
susan->age = 45;

push(&queue,samuel);
push(&queue,sally);
push(&queue,susan);

Employee* employee;
int i;
for(i = 0; i < 4; i++)
{
employee = (Employee*) pop(&queue);
printf("Popped %s\n",employee->name);
}
}


/**
*
* 简易二叉查找树
* 使用gcc编译
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _employee
{
char name[32];
unsigned char age;
} Employee;

int compareEmployee(Employee *e1,Employee *e2)
{
return strcmp(e1->name,e2->name);
}

void displayEmployee(Employee* employee)
{
printf("%s\t%d\n",employee->name,employee->age);
}

typedef struct _tree
{
void *data;
struct _tree *left;
struct _tree *right;
} TreeNode;

typedef void(*DISPLAY)(void*);
typedef int(*COMPARE)(void*,void*);

/*这里原书代码有错误,已修改*/
void insertTree(TreeNode **root,COMPARE compare,void *data)
{
TreeNode *node = (TreeNode*) malloc(sizeof(TreeNode));
node->data = data;
node->left = NULL;	/*设置为null,因为节点总是添加到叶子节点上*/
node->right = NULL;

if(*root == NULL)	/*构造树*/
{
*root = node;
return;
}

TreeNode* itr = *root;
while(1)
{
if(compare(itr->data,data) > 0)
{
if(itr->left != NULL)
{
itr = itr->left;
}
else
{
itr->left = node;
break;
}
}
else
{
if(itr->right != NULL)
{
itr = itr->right;
}
else
{
itr->right = node;
break;
}
}
}
}

/*中序遍历*/
void inOrder(TreeNode* root,DISPLAY display)
{
if(root != NULL)
{
inOrder(root->left,display);
display(root->data);
inOrder(root->right,display);
}
}

/*后续遍历*/
void postOrder(TreeNode* root,DISPLAY display)
{
if(root != NULL)
{
postOrder(root->left,display);
postOrder(root->right,display);
display(root->data);
}
}

/*前序遍历*/
void preOrder(TreeNode* root,DISPLAY display)
{
if(root != NULL)
{
display(root->data);
preOrder(root->left,display);
preOrder(root->right,display);
}
}

main()
{
Employee *samuel = (Employee*) malloc(sizeof(Employee));
strcpy(samuel->name,"Samuel");
samuel->age = 32;

Employee *sally = (Employee*) malloc(sizeof(Employee));
strcpy(sally->name,"Sally");
sally->age = 28;

Employee *susan = (Employee*) malloc(sizeof(Employee));
strcpy(susan->name,"Susan");
susan->age = 45;

Employee *porn = (Employee*) malloc(sizeof(Employee));
strcpy(porn->name,"porn");
porn->age = 46;

TreeNode* tree = NULL;
insertTree(&tree,(COMPARE) compareEmployee,samuel);
insertTree(&tree,(COMPARE) compareEmployee,sally);
insertTree(&tree,(COMPARE) compareEmployee,susan);
insertTree(&tree,(COMPARE) compareEmployee,porn);

printf("\npreOrder\n");
preOrder(tree,(DISPLAY) displayEmployee);
printf("\ninOrder\n");
inOrder(tree,(DISPLAY) displayEmployee);
printf("\npostOrder\n");
postOrder(tree,(DISPLAY) displayEmployee);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: