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

 指针和内存
当C程序被编译后,它与三种内存打交道
1.Static/Global
静态变量以及全局变量被分配到该部分内存,他们在程序开始运行时被创建直到程序运行结束后才回收生存期贯穿整个程序执行过程
2.Automatic(自动变量)
在函数中声明的变量在函数运行时创建,其范围仅限于函数内部,其生存期也仅限于函数执行时
3.Dynamic(动态内存分配)
内存从堆中分配并在必要时可以被释放

如图:

C语言参考中对语法和语意定义相当好,但是百密一疏,也有很多不确定的
1.Implementation-defined
2.Unspecified
 提供了一些实现但是没有文档描述。一个例子就是使用malloc()函数申请内存时参数传0。
3.Undefined
 因为没有任何要求,所以可能发生任何结果

 

星号*有三种意思
1.乘法如:1 * 2;
2.声明一个指针如:int* p;
3.求指针所指向的值如:*p = 3;

 

指针的实现其内部并没有任何可以判定指针所指内容是否合法或其所指向的数据类型。

 

Null的概念
The NULL macro 0强转为void指针,许多库中其定义为:#define NULL ((void*)0),这是我们通常认为的null指针,在很多头文件 stddef.h, stdlib.h, and stdio.h等都有定义
The ASCII NUL 字符串终结符,但并没有在任何标准头文件中定义,数值上用一个全0的byte表示
A null string 空字符串,不包含任何字符(an empty string and does not contain any characters)

 

Pointer to void(void指针)
void指针在表示以及内存对齐方面与char指针相同(注意是char指针,不是char)
除非两个void指针都被赋值为NULL,否则void指针不与任何指针相等。

 

如果一个指针被声明为全局或者静态变量,程序开始时他被初始化为NULL

int *globalpi;

void foo()
{
	static int *staticpi;
	...
}

main()
{
	...
}

内存分配示意图如下:

函数指针可能与数据指针的大小不同

 

Predefined Pointer-Related Types(与指针有关的预定义类型)
size_t,无符号数,malloc()参数就是它

#ifndef __SIZE_T
#define __SIZE_T
typedef unsigned int size_t;
#endif

ptrdiff_t 进行指针运算
intptr_t与uintptr_t
The types intptr_t and uintptr_t are used for storing pointer addresses. They provide a portable and safe way of declaring pointers, and will be the same size as the underlying pointer used on the system. They are useful for converting pointers to their integer representation.

 

尽量避免将指针转换为整形,在64位机器上如果整形只有4个字节则会出现信息丢失。

 

指针运算
1.指针与整数相加
2.指针与整数相减
3.两个指针相减
4.指针比较

 

void指针与加法
作为扩展,大多数编译器允许void指针进行指针运算,但是很可能编译器会报警告或者错误

int num = 5;
void* pv = #
printf("%p\n",pv);
pv = pv + 1;	/* 可能会有警告 */

两个指针相减

int vector[] = {28,41,7};
int *p0 = vector;
int *p1 = vector + 1;
int *p2 = vector + 2;

printf("p2-p0: %d\n",p2-p0);	/* p2-p0: 2 */
printf("p2-p1: %d\n",p2-p1);	/* p2-p1: 1 */
printf("p0-p1: %d\n",p0-p1);	/* p0-p1: -1 */

指针比较(略去)

 

常量与指针(Constants and Points)

 

指向常数的指针(Pointers to a constant)

指针可以被定义为指向常数。这意味着不能用指针修改其所指向的数据如:

int num = 5;
const int limit = 500;
int *pi;	//Pointer to an integer
const int *pci;		//Pointer to a constant integer
pi = #
pci = &limit;

指针本身可以被修改指向别的常整数(constant integer)或者简单常数,如:pci = #是合法的,但是*pci = 200;就会报语法错误,因为在用指针修改其所指向的内容。
下图中,虚线表示指针可以指向对应数据类型,pci指向的灰色方块表示不能用pci来修改。

将pci声明为指向常整数的指针意味着:

pci can be assigned to point to different constant integers
pci can be assigned to point to different nonconstant integers
pci can be dereferenced for reading purposes
pci cannot be dereferenced to change what it points to

The order of the type and the const keyword is not important. 下面两句是等价的

const int *pci;
int const *pci;

 

常量指针指向非常数(Constant pointers to nonconstants)

声明这种指针意味着指针本身不能改变,但是指针所指向的数据是可以改变的。例子如下:

int num;
int *const cpi = #

在这个声明中:
cpi必须被初始化为一个非常数的变量(cpi must be initialized to a nonconstant variable)
cpi不能被修改
cpi所指向的数据可被修改
如图:

可以使用cpi修改所指向的数据,如:*cpi = 25; 但如果初始化时将其指向常量limit,就会出现编译警告

const int limit = 200;
int *const cpi = &limit; /*warning: initialization discards qualifiers from pointer target type*/

一旦为cpi赋于一个地址后我们不能像下面一样在给其赋予别的值

int num;
int age;
int *const cpi = #
cpi = &age; /* 'cpi' : you cannot assign to a variable that is const */

 

指向常量的常量指针(Constant pointers to constants)
这种指针不常见,指针本身不能被修改,也不能通过指针修改其指向的数据,例子如下:
const int *const cpci = &limit;解释如下图:

这种指针声明后必须初始化如:

int num;
const int * const cpci = #

不初始化的话会报错,初始化以后再对指针赋值也会报错如:

cpci = &limit;
*cpci = 200;
这样也会报错

 

指向 指向常量的常量指针 的指针 Pointer to (constant pointer to constant)
吐槽一下:这丫的真是复杂
这种指针有多级间接指引(indirection),声明如下:

const int * const cpci = &limit;
const int * const * pcpci;	/* 声明这种指针 */如下图所示:



 

其使用如下:

printf("%d\n",*cpci);
pcpci = &cpci;
printf("%d\n",**pcpci);


常量与指针的对应关系如下图:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章