一、C语言中的指针
1.基本概念
C语言中指针(pointer)是一个变量,用来存储内存地址。通过指针,程序可以直接访问内存中的数据,包括变量、数组、结构体等等。指针在C语言中十分重要,因为它允许程序员直接操作内存,这在一些应用中非常有用。在C语言中,每个变量都有一个地址,可以通过取地址运算符(&)获取。例如以下指针语法:
int x = 5;
int *x_addr = &x; //int *x_addr指向整型变量x的地址; 例如值为0x7ffd2766a948
*x_addr = 6; //可以使用*运算符访问基础值
int x_value = *x_addr; //解引用,这将得到6
int arr1[10]; //数组隐含了指针!
int *arr2[20]; //指针数组,使arr2成为指向指针的指针
void *myPtr;
2.指针运算
假设char *c的值为0x100002,则
c++; // 0x100003
c += 4; // 0x100007
假设int *i的值为0x100002,则
i++; //0x100006
i += 4; //0x100016
原因:指针以基本数据类型的长度(以字节为单位)进行加减。
需要注意的是,指针可以指向任何位置,包括未分配的内存和其他程序的内存。这可能导致程序崩溃或者产生安全漏洞,因此需要谨慎使用指针。
二、C语言数组
C数组是存储特定数据类型的连续内存块。变量实际就是数组起始位置的指针。
char myString[40]; // myString的类型是char*
char *myArrayOfStrings[20]; // myArrayOfStrings的类型是char**
int counting[5] = {1, 2, 3, 4, 5}; // counting类型为int*
假设我们定义了int arr[4] = {5, 6, 7, 8},
那么下面这些是等价的
arr[2] = 7;
*(arr + 2) = 7; // 记住指针的算术运算!
三、C语言的位运算符
& (and/与): 10001 & 10000 -> 10000
| (or/或): 10001 | 10000 -> 10001
^ (xor/异或): 10001 ^ 10000 -> 00001
~ (complement/取反): ~10000 -> 01111
<< (left shift/左移): 1 << 4 -> 10000 (binary) -> 16 (decimal)
>> (right shfit/右移): 10101 >> 3 -> 10 (binary)
四、C语言类型转换
1.隐式类型转换
这种类型转换是在表达式求值过程中自动发生的,无需显式地进行类型转换。例如,将一个整数赋值给一个浮点数变量时,整数会自动转换为浮点数。
2.显式类型转换
这种类型转换需要使用显式的类型转换符来指定要转换的数据类型。例如,可以使用强制类型转换将一个整数转换为浮点数。在C语言中进行类型转换的语法是:(newType)variable。例如:
(char*)myVoidPtr;//将void*转换为char*
(uint64)(2 + 3);//从表达式转换为uint64
五、C语言的#include
.h
文件包含声明(构成)
.c
文件包含定义(实现)
include卫兵是指这样的结构
#ifndef XXXX_H
#define XXXX_H
...
#endif
六、C语言的内存
下面程序有什么错误?
char *makeABC() {
char y[3] = {'a', 'b', 'c'};
return y;
}
上述函数创建了一个包含 3 个元素的字符数组 y
,并将字符 'a'、'b' 和 'c' 赋值给它。然后它试图返回指向数组 y
的第一个元素的指针。但存在的问题是,一旦函数退出,变量 y
所占用的内存就会被释放,这意味着返回指向 y
的指针将指向一段无效的内存地址。因此,返回指向局部变量的指针是不安全的,可能会导致未定义的行为,如访问已释放的内存,从而导致程序崩溃或出现其他意外行为。
我们可以怎样解决呢?可以通过以下两种方法之一来修复代码:要么使用 malloc()
动态分配内存,要么将一个数组作为参数传递给函数。
//方法一:使用malloc()动态分配内存,注意不需要分配的内存时使用 free() 释放,否则可能会导致内存泄漏
char* makeABC() {
char* y = malloc(3 * sizeof(char));
y[0] = 'a';
y[1] = 'b';
y[2] = 'c';
return y;
}
//方法二:将数组作为参数传递给函数
//由于传递的是指向数组的指针,所以对数组所做的更改会保留在调用函数的作用域中
void makeABC(char* y) {
y[0] = 'a';
y[1] = 'b';
y[2] = 'c';
}
int main() {
char arr[3];//必须在调用函数之前创建一个字符数组
makeABC(arr);//并将其传递给函数,现在,arr 包含字符 'a'、'b' 和 'c'
return 0;
}