对C中const修饰指针的使用和理解

const用于定义常量类型,限定某些变量不允许修改。

const修饰指针时的原则:先忽略掉类型说明符,离谁近就修饰谁

1. 常量指针

常量指针:是指向常量的指针,指针指向地址中的内容是不可修改的,但是指针的指向是可以修改。

定义方式,以下2种都可以:

  1. const dataType *ptrName;
  2. dataType const *ptrName;
int a = 20;
int b = 30;
const int *ptr_i = &a;
// *ptr_i = 30; // 报错:read-only variable is not assignable 只读变量不可赋值
ptr_i = &b; // OK的

指针指向的内容不可修改,即:*ptrName(解引用时)表示的值不修改。

const修饰的是*ptr_i,所以不能修改的是就是 *ptr_i 的值。

2. 常指针(指针常量)

常指针:是指针类型的常量,即指针本身的值不可以修改,始终指向一个地址。因此常指针初始化需要给定一个地址值。但是指向地址的内容可以修改

定义方式,以下方式都是可以的(必须要初始化设置值):

  1. dataType *const ptrName;
  2. const *dataType ptrName;
int a = 20;
int *const ptr1 = &a;
//ptr1 = NULL; // 报错:cannot assign to variable 'ptr1' with const-qualified type 'int *const' 
*ptr1 = 30; // OK的

// 使用 typedef 定义一个别名
typedef int * intp_t;
int b = 30;
const intp_t p2 = &b;
p2 = &a; // 报错:表达式必须是可修改的左值

指针本身的值不可以修改,ptr1的值是&a,不可以修改,指针指向地址的内容可以修改即*ptr1(解引用时)表示的值可以修改。

const修饰的是ptr1,所以ptr1的值不能修改。

通过 typedef 定义指针类型别名intp_t后,再使用const 修饰 intp_t 变量,修饰的是指针本身,即指针本身的指向不可以修改。

3. 常指针&常量指针的复合使用

int a = 30;
const int *const ptr_a = &a; 

指针的地址值和地址值的内容 都不可以修改。

第一个const 修饰的是 *ptr_a,所以 *ptr_a 的值不能修改。

第二个const 修饰的是 ptr_a,所以 ptr_a的值也不能修改。

4. 其他

const 常用于修饰函数的参数,防止函数内部修改外部变量。

对C中typedef的使用和理解

typedef声明为已存在的数据类型取一个别名,可以用于替换复杂的类型名。

typedef是存储类型说明符(typedef、auto、register、static、extern、_Thread_local),由于声明中只允许一个存储类型说明符,因此typedef不能和他的存储类型说明符一起使用

使用代码示例说明

// 为整型定义一个别名int32
typedef int int32;

// 为 int* 指针定义一个别名
typedef int* int_ptr;

// 1.为 char 定义一个类型别名 char_t
// 2.为 char* 定义一个类型别名 char_p(char类型指针)
// 3.为 char (*)(void) 定义一个类型别名 fptr(函数指针)
typedef char char_t, *char_p, (*fptr)(void);

// 定义可变长度数组
typedef int A[];
// 使用时确定具体长度,a的类型是int[2], b的类型是 int[3]
A a = {1, 2}, b = {3,4,5};

// 为 int[5] 定义一个别名为arr
typedef int arr[5];

// 为结构体取别名
// 1.为 _node 定义一个别名 Node
// 2.为 _node* 定义一个别名 P_Node (指针)
typedef struct _node
{
   void* data;
   struct _node *pNext;  // 结构体自引用
} Node, *P_Node;

// 为 tageNode* 定义一个别名 pNode
typedef struct tagNode *pNode;
struct tageNode
{
    char *pItem;
    pNode pNext; // 结构体自引用
};

注意:结构体的自引用只能通过指针来引用。

通过上面的代码和说明可以看出:把typedef和别名去掉后,剩余部分就是别名代表的数据类型