数组不是指针 有更新! 2021-06-01 指针与数组 通过数组下标所能完成的任何操作都可以通过指针来实现。一般来说,用指针编写的程序比用数组下标编写的程序执行速度快,但另一方面,用指针实现的程序理解起来稍微困难一些。 声明一个数组 int a[10]; 定义一个长度为10的数组a。换句话说,它定义了一个由10个对象组成的集合,这10个对象存储在相邻的内存区域中,名字分别为a[0]、a[1]、a[2]、......、a[9]。 指向这个数组 int *pa = &a[0]; int x = *pa; 定义一个指向整型对象的指针,并将指针指向数组a的第0个元素。即,pa的值为数组元素a[0]的地址。将数组元素a[0]的值复制到变量x中。 如果pa指向数组中的某个特定的元素,那么,根据指针运算的定义,pa+1将指向下一个元素,pa+i将指向数组元素之后的第i个元素,而pa-i将指向pa所指向数组元素之前的第i个元素。因此,如果指针pa指向a[0],那么*(pa+1)引用的是数组元素a[1]的内容,pa+i是数组元素a[i]的地址,*(pa+i)引用的是数组元素a[i]的内容。 无论数组a中元素的类型或数组长度是什么,上面....
左值与右值 有更新! 2021-05-27 左值与右值? 左值(L-value)与右值(R-value),二者之间的区别是什么? 左值与右值 01 这两个术语是多年前由编译器设计者所创造并沿用至今的,尽管它们的定义并不与C语言严格吻合。 02 左值就是那些可以出现在赋值符号左边的东西;右值就是那些可以出现在赋值符号右边的东西。 这样的解释有些脱下裤子放屁的意思,通过名称我们也能得出左值和右值的意思,那么应该出现在赋值符号左边的东西是什么呢? 03 1. a = b + 1; 2. b + 1 = a; 在语句1中,a是一个左值,因为它标识了一个可以存储结果值的地点;b + 1是个右值,因为它指定了一个值。 那么,能像语句2一样,互换左右值的位置吗? 原先用作左值的a此时也可以作为右值,因为每个位置都包含一个值。然而,b + 1无法作为一个左值,因为它并未标识一个特定的位置。因此,语句2是非法的。 04 int a = 5; ++(a++); 如果尝试执行此段代码,则会出现如下报错 main.c:4:2: error: expression is not assignable ++(a++); ^ ~~~~~ 1 error ....
更好的使用结构体 有更新! 2020-11-15 结构体与指针 在C语言中,指针可以指向万物,自然也少不了结构体。 使用结构体指针,有4点好处: 就像指向数组的指针比数组本身更容易操控一样,指向结构的指针通常比结构本身更容易操控 在早期的C中,结构不能作为参数传递给函数,但是可以传递指向结构的指针 即使能传递一个结构,传递指针通常更有效率 一些用于表示数据的结构中包含指向其他结构的指针 根据这4点好处,证明学习结构体指针的重要性 // Book结构体沿用上面 int main(void) { struct Book books[2] = { {"C Primer Plus", "Stephen Prata", 59.4}, {"黑客与画家", "Paul Graham", 49.00} }; struct Book * book1; // 这是一个指向结构的指针 book1 = &books[0]; // 告诉编译器指针指向何处:结构数组第一个结构 printf("[book1] title = %s, author = %s, price = %f\n", book1->title, book1->autho....
结构体 2020-11-15 引子 设计程序时,最重要的步骤之一就是选择表示数据的方法。在许多情况下,简单变量甚至是数组还不够。为此,C提供了结构变量(structure variable)提高表示数据的能力,它能够创造新的形式。 建立结构体声明 小栗子 需求:需要打印一份图书目录。里面包含每本书的各种信息:书名、作者、出版社、版权日期和价格。其中一些元素(例如书名和作者)可以储存在字符数组中,其他项目需要一个int或者float。如果使用5哥不同的数组分别记录每一项都比较繁琐,尤其是要创建多份列表:一份按书名排序、一份按作者排序、一份按照价格排序等。如果能把图书目录的信息都包含在一个数组里更好,其中每个元素包含一本书的相关信息。 因此,就需要一种既能包含字符串也能包含数字的数据形式,而且还要保持各信息的独立。结构体就满足这种情况下的需求。 struct Book { /* 结构体模板:标记为Book (我们通常使用首字母大写的方式来标识结构体) */ char title[128]; // 成员 or 字段 char author[40]; char publisher[256]; int date; float....
c语言与动态内存 有更新! 2020-09-21 前言 在C语言中,除了获取变量的指针这种规矩的内存空间,我们还可以通过函数去申请指定大小的内存空间 动态 malloc malloc可以申请一块任意尺寸的空间,因为经常一段空间是连续的 #include <stdio.h> #include <stdlib.h> int main(void) { int *ptr = NULL; ptr = (int *) malloc(sizeof(int)); // malloc() 返回一个void *类型指针 if (ptr == NULL) { printf("获取内存失败"); exit(0); } *ptr = 4; printf("*ptr = %d\n", *ptr); return 0; } Output: *ptr = 4 解析 void * malloc(size_t size) 声明一个空指针 使用malloc函数申请一个连续空间,尺寸为int类型的长度,并将指针类型转换为int类型的指针 判断是否申请成功,若成功则继续,若不成功则退出 为ptr赋值 输出 可以在 (int *) malloc(s....
[头脑风暴]指针与函数还能擦出怎样的火花 有更新! 2020-08-28 Q 有一个名为selectMode的函数,它本身有一个char类型的参数,返回值是一个函数指针。这个函数指针也有两个参数,并且返回值类型为整形 int *fp(int, int) selectMode(char); 想法很好,但是编译器却一点都看不懂,因为这应该是两个语句,被糅杂到一行里,所以它就直接报错了 那我们一步一步来解析 首先,这个函数名为selectMode,所以我们要以selectMode为主体去写 第二,selectMode函数有一个char类型的参数 selectMode(char); 第三,函数的返回值是一个函数指针 *selectMode(char); 第四,函数指针也有两个int类型参数 (*selectMode(char))(int, int); 最后,返回值为int类型 int (*selectMode(char))(int, int); 这实际上就是函数指针与指针函数的结合体,在指针函数里套用函数指针 带入到实际应用中,通过selectMode的形参确定返回的是什么指针 int (*selectMode(char op))(int, int) { ....